1553: cleanup casts r=matklad a=matklad



Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2019-07-19 15:33:19 +00:00
commit 7bc9dec7cf
7 changed files with 976 additions and 855 deletions

View File

@ -25,6 +25,12 @@ impl<A, B> Either<A, B> {
Either::B(b) => Either::B(f2(b)), Either::B(b) => Either::B(f2(b)),
} }
} }
pub fn map_a<U, F>(self, f: F) -> Either<U, B>
where
F: FnOnce(A) -> U,
{
self.map(f, |it| it)
}
pub fn a(self) -> Option<A> { pub fn a(self) -> Option<A> {
match self { match self {
Either::A(it) => Some(it), Either::A(it) => Some(it),

View File

@ -564,11 +564,7 @@ where
.else_branch() .else_branch()
.map(|b| match b { .map(|b| match b {
ast::ElseBranch::Block(it) => self.collect_block(it), ast::ElseBranch::Block(it) => self.collect_block(it),
ast::ElseBranch::IfExpr(elif) => { ast::ElseBranch::IfExpr(elif) => self.collect_expr(elif.into()),
let expr: ast::Expr =
ast::Expr::cast(elif.syntax().clone()).unwrap();
self.collect_expr(expr)
}
}) })
.unwrap_or_else(|| self.empty_block()); .unwrap_or_else(|| self.empty_block());
let placeholder_pat = self.pats.alloc(Pat::Missing); let placeholder_pat = self.pats.alloc(Pat::Missing);

View File

@ -309,15 +309,11 @@ impl SourceAnalyzer {
crate::Resolution::LocalBinding(it) => { crate::Resolution::LocalBinding(it) => {
// We get a `PatId` from resolver, but it actually can only // We get a `PatId` from resolver, but it actually can only
// point at `BindPat`, and not at the arbitrary pattern. // point at `BindPat`, and not at the arbitrary pattern.
let pat_ptr = self.body_source_map.as_ref()?.pat_syntax(it)?; let pat_ptr = self
let pat_ptr = match pat_ptr { .body_source_map
Either::A(pat) => { .as_ref()?
let pat: AstPtr<ast::BindPat> = .pat_syntax(it)?
pat.cast_checking_kind(|kind| kind == BIND_PAT).unwrap(); .map_a(|ptr| ptr.cast::<ast::BindPat>().unwrap());
Either::A(pat)
}
Either::B(self_param) => Either::B(self_param),
};
PathResolution::LocalBinding(pat_ptr) PathResolution::LocalBinding(pat_ptr)
} }
crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it), crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),

View File

@ -10,7 +10,7 @@ use std::marker::PhantomData;
use crate::{ use crate::{
syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken}, syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken},
SmolStr, SmolStr, SyntaxKind,
}; };
pub use self::{ pub use self::{
@ -26,6 +26,8 @@ pub use self::{
/// the same representation: a pointer to the tree root and a pointer to the /// the same representation: a pointer to the tree root and a pointer to the
/// node itself. /// node itself.
pub trait AstNode: Clone { pub trait AstNode: Clone {
fn can_cast(kind: SyntaxKind) -> bool;
fn cast(syntax: SyntaxNode) -> Option<Self> fn cast(syntax: SyntaxNode) -> Option<Self>
where where
Self: Sized; Self: Sized;

File diff suppressed because it is too large Load Diff

View File

@ -12,18 +12,34 @@ the below applies to the result of this template
#![cfg_attr(rustfmt, rustfmt_skip)] #![cfg_attr(rustfmt, rustfmt_skip)]
use crate::{ use crate::{
SyntaxNode, SyntaxKind::*, SyntaxNode, SyntaxKind::{self, *},
ast::{self, AstNode}, ast::{self, AstNode},
}; };
{% for node, methods in ast %} {% for node, methods in ast %}
// {{ node }} // {{ node }}
{%- if methods.enum %}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct {{ node }} { pub struct {{ node }} {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
} }
impl AstNode for {{ node }} {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
{%- if methods.enum %}
{% for kind in methods.enum %} | {{ kind | SCREAM }} {%- endfor -%}
{% else %}
{{ node | SCREAM }}
{%- endif %} => true,
_ => false,
}
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) { Some({{ node }} { syntax }) } else { None }
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
{% if methods.enum %}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum {{ node }}Kind { pub enum {{ node }}Kind {
{%- for kind in methods.enum %} {%- for kind in methods.enum %}
@ -33,25 +49,9 @@ pub enum {{ node }}Kind {
{%- for kind in methods.enum %} {%- for kind in methods.enum %}
impl From<{{ kind }}> for {{ node }} { impl From<{{ kind }}> for {{ node }} {
fn from(n: {{ kind }}) -> {{ node }} { fn from(n: {{ kind }}) -> {{ node }} { {{ node }} { syntax: n.syntax } }
{{ node }}::cast(n.syntax).unwrap()
}
} }
{%- endfor %} {%- endfor %}
impl AstNode for {{ node }} {
fn cast(syntax: SyntaxNode) -> Option<Self> {
match syntax.kind() {
{%- for kind in methods.enum %}
| {{ kind | SCREAM }}
{%- endfor %} => Some({{ node }} { syntax }),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl {{ node }} { impl {{ node }} {
pub fn kind(&self) -> {{ node }}Kind { pub fn kind(&self) -> {{ node }}Kind {
match self.syntax.kind() { match self.syntax.kind() {
@ -62,22 +62,6 @@ impl {{ node }} {
} }
} }
} }
{% else %}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct {{ node }} {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for {{ node }} {
fn cast(syntax: SyntaxNode) -> Option<Self> {
match syntax.kind() {
{{ node | SCREAM }} => Some({{ node }} { syntax }),
_ => None,
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
{% endif %} {% endif %}
{% if methods.traits -%} {% if methods.traits -%}

View File

@ -61,12 +61,8 @@ impl<N: AstNode> AstPtr<N> {
self.raw self.raw
} }
// FIXME: extend AstNode to do this safely pub fn cast<U: AstNode>(self) -> Option<AstPtr<U>> {
pub fn cast_checking_kind<U: AstNode>( if !U::can_cast(self.raw.kind()) {
self,
cond: impl FnOnce(SyntaxKind) -> bool,
) -> Option<AstPtr<U>> {
if !cond(self.raw.kind()) {
return None; return None;
} }
Some(AstPtr { raw: self.raw, _ty: PhantomData }) Some(AstPtr { raw: self.raw, _ty: PhantomData })