From 4768f5e7177159b894d65a50b1e4492cb4048ac3 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 22 Aug 2019 17:43:09 +0200 Subject: Improve/fix type bound lowering --- crates/ra_hir/src/ty/tests.rs | 33 ++++++++++++++++++++ crates/ra_hir/src/type_ref.rs | 6 ++-- crates/ra_syntax/src/ast/extensions.rs | 55 ++++++++++++++++++---------------- 3 files changed, 64 insertions(+), 30 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 41cea9564..c5818b738 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -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::(file.syntax(), pos.offset).unwrap(); diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs index 949fa7a2c..fa91bfb22 100644 --- a/crates/ra_hir/src/type_ref.rs +++ b/crates/ra_hir/src/type_ref.rs @@ -136,7 +136,7 @@ pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option) 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, } } } diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index 8de979ca2..e0ea3e5ab 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -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 { + self.syntax() + .children_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == LIFETIME) + } + pub fn question_mark_token(&self) -> Option { 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 { - 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!(), - } - } -} -- cgit v1.2.3