diff options
author | Florian Diebold <[email protected]> | 2019-08-22 16:43:09 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-08-22 20:58:29 +0100 |
commit | 4768f5e7177159b894d65a50b1e4492cb4048ac3 (patch) | |
tree | de5d4388124443eb51847a390f259acd44ef1a65 /crates | |
parent | b1a40042e8f595af0486cf1cc70b63be1ff302b3 (diff) |
Improve/fix type bound lowering
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/type_ref.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 55 |
3 files changed, 64 insertions, 30 deletions
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 { | |||
3415 | ); | 3415 | ); |
3416 | } | 3416 | } |
3417 | 3417 | ||
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 | |||
3418 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 3451 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
3419 | let file = db.parse(pos.file_id).ok().unwrap(); | 3452 | let file = db.parse(pos.file_id).ok().unwrap(); |
3420 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 3453 | let expr = algo::find_node_at_offset::<ast::Expr>(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<ast::TypeBoundList>) | |||
136 | impl TypeBound { | 136 | impl TypeBound { |
137 | pub(crate) fn from_ast(node: ast::TypeBound) -> Self { | 137 | pub(crate) fn from_ast(node: ast::TypeBound) -> Self { |
138 | match node.kind() { | 138 | match node.kind() { |
139 | Some(ast::TypeBoundKind::PathType(path_type)) => { | 139 | ast::TypeBoundKind::PathType(path_type) => { |
140 | let path = match path_type.path() { | 140 | let path = match path_type.path() { |
141 | Some(p) => p, | 141 | Some(p) => p, |
142 | None => return TypeBound::Error, | 142 | None => return TypeBound::Error, |
@@ -147,9 +147,7 @@ impl TypeBound { | |||
147 | }; | 147 | }; |
148 | TypeBound::Path(path) | 148 | TypeBound::Path(path) |
149 | } | 149 | } |
150 | Some(ast::TypeBoundKind::ForType(_)) | Some(ast::TypeBoundKind::Lifetime(_)) | None => { | 150 | ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error, |
151 | TypeBound::Error | ||
152 | } | ||
153 | } | 151 | } |
154 | } | 152 | } |
155 | } | 153 | } |
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 { | |||
382 | } | 382 | } |
383 | } | 383 | } |
384 | 384 | ||
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 | |||
385 | impl ast::TypeBound { | 395 | 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 | |||
386 | pub fn question_mark_token(&self) -> Option<SyntaxToken> { | 415 | pub fn question_mark_token(&self) -> Option<SyntaxToken> { |
387 | self.syntax() | 416 | self.syntax() |
388 | .children_with_tokens() | 417 | .children_with_tokens() |
@@ -399,29 +428,3 @@ impl ast::TraitDef { | |||
399 | self.syntax().children_with_tokens().any(|t| t.kind() == T![auto]) | 428 | self.syntax().children_with_tokens().any(|t| t.kind() == T![auto]) |
400 | } | 429 | } |
401 | } | 430 | } |
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 | } | ||