aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_cfg/src/lib.rs5
-rw-r--r--crates/ra_fmt/src/lib.rs5
-rw-r--r--crates/ra_hir/src/expr.rs428
-rw-r--r--crates/ra_hir/src/expr/lower.rs84
-rw-r--r--crates/ra_hir/src/source_binder.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs11
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs12
-rw-r--r--crates/ra_hir/src/ty/lower.rs38
-rw-r--r--crates/ra_hir/src/ty/primitive.rs26
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/body/lower.rs49
-rw-r--r--crates/ra_hir_def/src/builtin_type.rs86
-rw-r--r--crates/ra_hir_def/src/expr.rs419
-rw-r--r--crates/ra_hir_def/src/lib.rs2
-rw-r--r--xtask/tests/tidy-tests/docs.rs49
15 files changed, 664 insertions, 554 deletions
diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs
index 1bee3eb99..51d953f6e 100644
--- a/crates/ra_cfg/src/lib.rs
+++ b/crates/ra_cfg/src/lib.rs
@@ -1,11 +1,12 @@
1//! ra_cfg defines conditional compiling options, `cfg` attibute parser and evaluator 1//! ra_cfg defines conditional compiling options, `cfg` attibute parser and evaluator
2
3mod cfg_expr;
4
2use std::iter::IntoIterator; 5use std::iter::IntoIterator;
3 6
4use ra_syntax::SmolStr; 7use ra_syntax::SmolStr;
5use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
6 9
7mod cfg_expr;
8
9pub use cfg_expr::{parse_cfg, CfgExpr}; 10pub use cfg_expr::{parse_cfg, CfgExpr};
10 11
11/// Configuration options used for conditional compilition on items with `cfg` attributes. 12/// Configuration options used for conditional compilition on items with `cfg` attributes.
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index e22ac9753..a30ed4cbb 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -1,5 +1,7 @@
1//! This crate provides some utilities for indenting rust code. 1//! This crate provides some utilities for indenting rust code.
2//! 2
3use std::iter::successors;
4
3use itertools::Itertools; 5use itertools::Itertools;
4use ra_syntax::{ 6use ra_syntax::{
5 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
@@ -7,7 +9,6 @@ use ra_syntax::{
7 SyntaxKind::*, 9 SyntaxKind::*,
8 SyntaxNode, SyntaxToken, T, 10 SyntaxNode, SyntaxToken, T,
9}; 11};
10use std::iter::successors;
11 12
12pub fn reindent(text: &str, indent: &str) -> String { 13pub fn reindent(text: &str, indent: &str) -> String {
13 let indent = format!("\n{}", indent); 14 let indent = format!("\n{}", indent);
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 53da7f0bf..ddf605111 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -6,35 +6,22 @@ pub(crate) mod validation;
6 6
7use std::{ops::Index, sync::Arc}; 7use std::{ops::Index, sync::Arc};
8 8
9use hir_def::{ 9use ra_arena::{map::ArenaMap, Arena};
10 path::GenericArgs,
11 type_ref::{Mutability, TypeRef},
12};
13use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
14use ra_syntax::{ast, AstPtr}; 10use ra_syntax::{ast, AstPtr};
15use rustc_hash::FxHashMap; 11use rustc_hash::FxHashMap;
16 12
17use crate::{ 13use crate::{db::HirDatabase, DefWithBody, Either, HasSource, Resolver, Source};
18 db::HirDatabase,
19 ty::primitive::{UncertainFloatTy, UncertainIntTy},
20 DefWithBody, Either, HasSource, Name, Path, Resolver, Source,
21};
22 14
23pub use self::scope::ExprScopes; 15pub use self::scope::ExprScopes;
24 16
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 17pub use hir_def::expr::{
26pub struct ExprId(RawId); 18 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, MatchArm,
27impl_arena_id!(ExprId); 19 Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
28 20};
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub struct PatId(RawId);
31impl_arena_id!(PatId);
32 21
33/// The body of an item (function, const etc.). 22/// The body of an item (function, const etc.).
34#[derive(Debug, Eq, PartialEq)] 23#[derive(Debug, Eq, PartialEq)]
35pub struct Body { 24pub struct Body {
36 /// The def of the item this body belongs to
37 owner: DefWithBody,
38 exprs: Arena<ExprId, Expr>, 25 exprs: Arena<ExprId, Expr>,
39 pats: Arena<PatId, Pat>, 26 pats: Arena<PatId, Pat>,
40 /// The patterns for the function's parameters. While the parameter types are 27 /// The patterns for the function's parameters. While the parameter types are
@@ -97,7 +84,7 @@ impl Body {
97 } 84 }
98 }; 85 };
99 86
100 let (body, source_map) = lower::lower(db, def.resolver(db), file_id, def, params, body); 87 let (body, source_map) = lower::lower(db, def.resolver(db), file_id, params, body);
101 (Arc::new(body), Arc::new(source_map)) 88 (Arc::new(body), Arc::new(source_map))
102 } 89 }
103 90
@@ -113,10 +100,6 @@ impl Body {
113 self.body_expr 100 self.body_expr
114 } 101 }
115 102
116 pub fn owner(&self) -> DefWithBody {
117 self.owner
118 }
119
120 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> { 103 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
121 self.exprs.iter() 104 self.exprs.iter()
122 } 105 }
@@ -128,21 +111,21 @@ impl Body {
128 111
129// needs arbitrary_self_types to be a method... or maybe move to the def? 112// needs arbitrary_self_types to be a method... or maybe move to the def?
130pub(crate) fn resolver_for_expr( 113pub(crate) fn resolver_for_expr(
131 body: Arc<Body>,
132 db: &impl HirDatabase, 114 db: &impl HirDatabase,
115 owner: DefWithBody,
133 expr_id: ExprId, 116 expr_id: ExprId,
134) -> Resolver { 117) -> Resolver {
135 let scopes = db.expr_scopes(body.owner); 118 let scopes = db.expr_scopes(owner);
136 resolver_for_scope(body, db, scopes.scope_for(expr_id)) 119 resolver_for_scope(db, owner, scopes.scope_for(expr_id))
137} 120}
138 121
139pub(crate) fn resolver_for_scope( 122pub(crate) fn resolver_for_scope(
140 body: Arc<Body>,
141 db: &impl HirDatabase, 123 db: &impl HirDatabase,
124 owner: DefWithBody,
142 scope_id: Option<scope::ScopeId>, 125 scope_id: Option<scope::ScopeId>,
143) -> Resolver { 126) -> Resolver {
144 let mut r = body.owner.resolver(db); 127 let mut r = owner.resolver(db);
145 let scopes = db.expr_scopes(body.owner); 128 let scopes = db.expr_scopes(owner);
146 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>(); 129 let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
147 for scope in scope_chain.into_iter().rev() { 130 for scope in scope_chain.into_iter().rev() {
148 r = r.push_expr_scope(Arc::clone(&scopes), scope); 131 r = r.push_expr_scope(Arc::clone(&scopes), scope);
@@ -187,388 +170,3 @@ impl BodySourceMap {
187 self.field_map[&(expr, field)] 170 self.field_map[&(expr, field)]
188 } 171 }
189} 172}
190
191#[derive(Debug, Clone, Eq, PartialEq)]
192pub enum Literal {
193 String(String),
194 ByteString(Vec<u8>),
195 Char(char),
196 Bool(bool),
197 Int(u64, UncertainIntTy),
198 Float(u64, UncertainFloatTy), // FIXME: f64 is not Eq
199}
200
201#[derive(Debug, Clone, Eq, PartialEq)]
202pub enum Expr {
203 /// This is produced if syntax tree does not have a required expression piece.
204 Missing,
205 Path(Path),
206 If {
207 condition: ExprId,
208 then_branch: ExprId,
209 else_branch: Option<ExprId>,
210 },
211 Block {
212 statements: Vec<Statement>,
213 tail: Option<ExprId>,
214 },
215 Loop {
216 body: ExprId,
217 },
218 While {
219 condition: ExprId,
220 body: ExprId,
221 },
222 For {
223 iterable: ExprId,
224 pat: PatId,
225 body: ExprId,
226 },
227 Call {
228 callee: ExprId,
229 args: Vec<ExprId>,
230 },
231 MethodCall {
232 receiver: ExprId,
233 method_name: Name,
234 args: Vec<ExprId>,
235 generic_args: Option<GenericArgs>,
236 },
237 Match {
238 expr: ExprId,
239 arms: Vec<MatchArm>,
240 },
241 Continue,
242 Break {
243 expr: Option<ExprId>,
244 },
245 Return {
246 expr: Option<ExprId>,
247 },
248 RecordLit {
249 path: Option<Path>,
250 fields: Vec<RecordLitField>,
251 spread: Option<ExprId>,
252 },
253 Field {
254 expr: ExprId,
255 name: Name,
256 },
257 Await {
258 expr: ExprId,
259 },
260 Try {
261 expr: ExprId,
262 },
263 TryBlock {
264 body: ExprId,
265 },
266 Cast {
267 expr: ExprId,
268 type_ref: TypeRef,
269 },
270 Ref {
271 expr: ExprId,
272 mutability: Mutability,
273 },
274 Box {
275 expr: ExprId,
276 },
277 UnaryOp {
278 expr: ExprId,
279 op: UnaryOp,
280 },
281 BinaryOp {
282 lhs: ExprId,
283 rhs: ExprId,
284 op: Option<BinaryOp>,
285 },
286 Index {
287 base: ExprId,
288 index: ExprId,
289 },
290 Lambda {
291 args: Vec<PatId>,
292 arg_types: Vec<Option<TypeRef>>,
293 body: ExprId,
294 },
295 Tuple {
296 exprs: Vec<ExprId>,
297 },
298 Array(Array),
299 Literal(Literal),
300}
301
302#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
303pub enum BinaryOp {
304 LogicOp(LogicOp),
305 ArithOp(ArithOp),
306 CmpOp(CmpOp),
307 Assignment { op: Option<ArithOp> },
308}
309
310#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
311pub enum LogicOp {
312 And,
313 Or,
314}
315
316#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
317pub enum CmpOp {
318 Eq { negated: bool },
319 Ord { ordering: Ordering, strict: bool },
320}
321
322#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
323pub enum Ordering {
324 Less,
325 Greater,
326}
327
328#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
329pub enum ArithOp {
330 Add,
331 Mul,
332 Sub,
333 Div,
334 Rem,
335 Shl,
336 Shr,
337 BitXor,
338 BitOr,
339 BitAnd,
340}
341
342pub use ra_syntax::ast::PrefixOp as UnaryOp;
343#[derive(Debug, Clone, Eq, PartialEq)]
344pub enum Array {
345 ElementList(Vec<ExprId>),
346 Repeat { initializer: ExprId, repeat: ExprId },
347}
348
349#[derive(Debug, Clone, Eq, PartialEq)]
350pub struct MatchArm {
351 pub pats: Vec<PatId>,
352 pub guard: Option<ExprId>,
353 pub expr: ExprId,
354}
355
356#[derive(Debug, Clone, Eq, PartialEq)]
357pub struct RecordLitField {
358 pub name: Name,
359 pub expr: ExprId,
360}
361
362#[derive(Debug, Clone, Eq, PartialEq)]
363pub enum Statement {
364 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> },
365 Expr(ExprId),
366}
367
368impl Expr {
369 pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
370 match self {
371 Expr::Missing => {}
372 Expr::Path(_) => {}
373 Expr::If { condition, then_branch, else_branch } => {
374 f(*condition);
375 f(*then_branch);
376 if let Some(else_branch) = else_branch {
377 f(*else_branch);
378 }
379 }
380 Expr::Block { statements, tail } => {
381 for stmt in statements {
382 match stmt {
383 Statement::Let { initializer, .. } => {
384 if let Some(expr) = initializer {
385 f(*expr);
386 }
387 }
388 Statement::Expr(e) => f(*e),
389 }
390 }
391 if let Some(expr) = tail {
392 f(*expr);
393 }
394 }
395 Expr::TryBlock { body } => f(*body),
396 Expr::Loop { body } => f(*body),
397 Expr::While { condition, body } => {
398 f(*condition);
399 f(*body);
400 }
401 Expr::For { iterable, body, .. } => {
402 f(*iterable);
403 f(*body);
404 }
405 Expr::Call { callee, args } => {
406 f(*callee);
407 for arg in args {
408 f(*arg);
409 }
410 }
411 Expr::MethodCall { receiver, args, .. } => {
412 f(*receiver);
413 for arg in args {
414 f(*arg);
415 }
416 }
417 Expr::Match { expr, arms } => {
418 f(*expr);
419 for arm in arms {
420 f(arm.expr);
421 }
422 }
423 Expr::Continue => {}
424 Expr::Break { expr } | Expr::Return { expr } => {
425 if let Some(expr) = expr {
426 f(*expr);
427 }
428 }
429 Expr::RecordLit { fields, spread, .. } => {
430 for field in fields {
431 f(field.expr);
432 }
433 if let Some(expr) = spread {
434 f(*expr);
435 }
436 }
437 Expr::Lambda { body, .. } => {
438 f(*body);
439 }
440 Expr::BinaryOp { lhs, rhs, .. } => {
441 f(*lhs);
442 f(*rhs);
443 }
444 Expr::Index { base, index } => {
445 f(*base);
446 f(*index);
447 }
448 Expr::Field { expr, .. }
449 | Expr::Await { expr }
450 | Expr::Try { expr }
451 | Expr::Cast { expr, .. }
452 | Expr::Ref { expr, .. }
453 | Expr::UnaryOp { expr, .. }
454 | Expr::Box { expr } => {
455 f(*expr);
456 }
457 Expr::Tuple { exprs } => {
458 for expr in exprs {
459 f(*expr);
460 }
461 }
462 Expr::Array(a) => match a {
463 Array::ElementList(exprs) => {
464 for expr in exprs {
465 f(*expr);
466 }
467 }
468 Array::Repeat { initializer, repeat } => {
469 f(*initializer);
470 f(*repeat)
471 }
472 },
473 Expr::Literal(_) => {}
474 }
475 }
476}
477
478/// Explicit binding annotations given in the HIR for a binding. Note
479/// that this is not the final binding *mode* that we infer after type
480/// inference.
481#[derive(Clone, PartialEq, Eq, Debug, Copy)]
482pub enum BindingAnnotation {
483 /// No binding annotation given: this means that the final binding mode
484 /// will depend on whether we have skipped through a `&` reference
485 /// when matching. For example, the `x` in `Some(x)` will have binding
486 /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
487 /// ultimately be inferred to be by-reference.
488 Unannotated,
489
490 /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
491 Mutable,
492
493 /// Annotated as `ref`, like `ref x`
494 Ref,
495
496 /// Annotated as `ref mut x`.
497 RefMut,
498}
499
500impl BindingAnnotation {
501 fn new(is_mutable: bool, is_ref: bool) -> Self {
502 match (is_mutable, is_ref) {
503 (true, true) => BindingAnnotation::RefMut,
504 (false, true) => BindingAnnotation::Ref,
505 (true, false) => BindingAnnotation::Mutable,
506 (false, false) => BindingAnnotation::Unannotated,
507 }
508 }
509}
510
511#[derive(Debug, Clone, Eq, PartialEq)]
512pub struct RecordFieldPat {
513 pub(crate) name: Name,
514 pub(crate) pat: PatId,
515}
516
517/// Close relative to rustc's hir::PatKind
518#[derive(Debug, Clone, Eq, PartialEq)]
519pub enum Pat {
520 Missing,
521 Wild,
522 Tuple(Vec<PatId>),
523 Record {
524 path: Option<Path>,
525 args: Vec<RecordFieldPat>,
526 // FIXME: 'ellipsis' option
527 },
528 Range {
529 start: ExprId,
530 end: ExprId,
531 },
532 Slice {
533 prefix: Vec<PatId>,
534 rest: Option<PatId>,
535 suffix: Vec<PatId>,
536 },
537 Path(Path),
538 Lit(ExprId),
539 Bind {
540 mode: BindingAnnotation,
541 name: Name,
542 subpat: Option<PatId>,
543 },
544 TupleStruct {
545 path: Option<Path>,
546 args: Vec<PatId>,
547 },
548 Ref {
549 pat: PatId,
550 mutability: Mutability,
551 },
552}
553
554impl Pat {
555 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
556 match self {
557 Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {}
558 Pat::Bind { subpat, .. } => {
559 subpat.iter().copied().for_each(f);
560 }
561 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => {
562 args.iter().copied().for_each(f);
563 }
564 Pat::Ref { pat, .. } => f(*pat),
565 Pat::Slice { prefix, rest, suffix } => {
566 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
567 total_iter.copied().for_each(f);
568 }
569 Pat::Record { args, .. } => {
570 args.iter().map(|f| f.pat).for_each(f);
571 }
572 }
573 }
574}
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index 6463dd65e..adc68b23c 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -1,6 +1,10 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{path::GenericArgs, type_ref::TypeRef}; 3use hir_def::{
4 builtin_type::{BuiltinFloat, BuiltinInt},
5 path::GenericArgs,
6 type_ref::TypeRef,
7};
4use hir_expand::{ 8use hir_expand::{
5 hygiene::Hygiene, 9 hygiene::Hygiene,
6 name::{self, AsName, Name}, 10 name::{self, AsName, Name},
@@ -16,22 +20,19 @@ use ra_syntax::{
16use test_utils::tested_by; 20use test_utils::tested_by;
17 21
18use crate::{ 22use crate::{
19 db::HirDatabase, 23 db::HirDatabase, AstId, Either, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path,
20 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, 24 Resolver, Source,
21 AstId, DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path, Resolver,
22 Source,
23}; 25};
24 26
25use super::{ 27use super::{
26 ArithOp, Array, BinaryOp, BindingAnnotation, Body, BodySourceMap, CmpOp, Expr, ExprId, Literal, 28 Array, BinaryOp, BindingAnnotation, Body, BodySourceMap, Expr, ExprId, Literal, MatchArm, Pat,
27 LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField, Statement, 29 PatId, PatPtr, RecordFieldPat, RecordLitField, Statement,
28}; 30};
29 31
30pub(super) fn lower( 32pub(super) fn lower(
31 db: &impl HirDatabase, 33 db: &impl HirDatabase,
32 resolver: Resolver, 34 resolver: Resolver,
33 file_id: HirFileId, 35 file_id: HirFileId,
34 owner: DefWithBody,
35 params: Option<ast::ParamList>, 36 params: Option<ast::ParamList>,
36 body: Option<ast::Expr>, 37 body: Option<ast::Expr>,
37) -> (Body, BodySourceMap) { 38) -> (Body, BodySourceMap) {
@@ -42,11 +43,10 @@ pub(super) fn lower(
42 current_file_id: file_id, 43 current_file_id: file_id,
43 source_map: BodySourceMap::default(), 44 source_map: BodySourceMap::default(),
44 body: Body { 45 body: Body {
45 owner,
46 exprs: Arena::default(), 46 exprs: Arena::default(),
47 pats: Arena::default(), 47 pats: Arena::default(),
48 params: Vec::new(), 48 params: Vec::new(),
49 body_expr: ExprId((!0).into()), 49 body_expr: ExprId::dummy(),
50 }, 50 },
51 } 51 }
52 .collect(params, body) 52 .collect(params, body)
@@ -423,28 +423,18 @@ where
423 ast::Expr::Literal(e) => { 423 ast::Expr::Literal(e) => {
424 let lit = match e.kind() { 424 let lit = match e.kind() {
425 LiteralKind::IntNumber { suffix } => { 425 LiteralKind::IntNumber { suffix } => {
426 let known_name = suffix 426 let known_name = suffix.and_then(|it| BuiltinInt::from_suffix(&it));
427 .and_then(|it| IntTy::from_suffix(&it).map(UncertainIntTy::Known));
428 427
429 Literal::Int( 428 Literal::Int(Default::default(), known_name)
430 Default::default(),
431 known_name.unwrap_or(UncertainIntTy::Unknown),
432 )
433 } 429 }
434 LiteralKind::FloatNumber { suffix } => { 430 LiteralKind::FloatNumber { suffix } => {
435 let known_name = suffix 431 let known_name = suffix.and_then(|it| BuiltinFloat::from_suffix(&it));
436 .and_then(|it| FloatTy::from_suffix(&it).map(UncertainFloatTy::Known));
437 432
438 Literal::Float( 433 Literal::Float(Default::default(), known_name)
439 Default::default(),
440 known_name.unwrap_or(UncertainFloatTy::Unknown),
441 )
442 } 434 }
443 LiteralKind::ByteString => Literal::ByteString(Default::default()), 435 LiteralKind::ByteString => Literal::ByteString(Default::default()),
444 LiteralKind::String => Literal::String(Default::default()), 436 LiteralKind::String => Literal::String(Default::default()),
445 LiteralKind::Byte => { 437 LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)),
446 Literal::Int(Default::default(), UncertainIntTy::Known(IntTy::u8()))
447 }
448 LiteralKind::Bool => Literal::Bool(Default::default()), 438 LiteralKind::Bool => Literal::Bool(Default::default()),
449 LiteralKind::Char => Literal::Char(Default::default()), 439 LiteralKind::Char => Literal::Char(Default::default()),
450 }; 440 };
@@ -601,47 +591,3 @@ where
601 Path::from_src(path, &hygiene) 591 Path::from_src(path, &hygiene)
602 } 592 }
603} 593}
604
605impl From<ast::BinOp> for BinaryOp {
606 fn from(ast_op: ast::BinOp) -> Self {
607 match ast_op {
608 ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
609 ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
610 ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
611 ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
612 ast::BinOp::LesserEqualTest => {
613 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
614 }
615 ast::BinOp::GreaterEqualTest => {
616 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
617 }
618 ast::BinOp::LesserTest => {
619 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
620 }
621 ast::BinOp::GreaterTest => {
622 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
623 }
624 ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
625 ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
626 ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
627 ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
628 ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
629 ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
630 ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
631 ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
632 ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
633 ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
634 ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
635 ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
636 ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
637 ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
638 ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
639 ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
640 ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
641 ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
642 ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
643 ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
644 ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
645 }
646 }
647}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index fe4211819..f28e9c931 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -150,7 +150,7 @@ impl SourceAnalyzer {
150 None => scope_for(&scopes, &source_map, &node), 150 None => scope_for(&scopes, &source_map, &node),
151 Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), 151 Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset),
152 }; 152 };
153 let resolver = expr::resolver_for_scope(def.body(db), db, scope); 153 let resolver = expr::resolver_for_scope(db, def, scope);
154 SourceAnalyzer { 154 SourceAnalyzer {
155 resolver, 155 resolver,
156 body_owner: Some(def), 156 body_owner: Some(def),
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 2370e8d4f..f17c6c614 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -43,7 +43,7 @@ use crate::{
43 expr::{BindingAnnotation, Body, ExprId, PatId}, 43 expr::{BindingAnnotation, Body, ExprId, PatId},
44 resolve::{Resolver, TypeNs}, 44 resolve::{Resolver, TypeNs},
45 ty::infer::diagnostics::InferenceDiagnostic, 45 ty::infer::diagnostics::InferenceDiagnostic,
46 Adt, AssocItem, ConstData, DefWithBody, FnData, Function, HasBody, Path, StructField, 46 Adt, AssocItem, ConstData, DefWithBody, FnData, Function, Path, StructField,
47}; 47};
48 48
49macro_rules! ty_app { 49macro_rules! ty_app {
@@ -64,9 +64,8 @@ mod coerce;
64/// The entry point of type inference. 64/// The entry point of type inference.
65pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 65pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
66 let _p = profile("infer_query"); 66 let _p = profile("infer_query");
67 let body = def.body(db);
68 let resolver = def.resolver(db); 67 let resolver = def.resolver(db);
69 let mut ctx = InferenceContext::new(db, body, resolver); 68 let mut ctx = InferenceContext::new(db, def, resolver);
70 69
71 match def { 70 match def {
72 DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)), 71 DefWithBody::Const(ref c) => ctx.collect_const(&c.data(db)),
@@ -187,6 +186,7 @@ impl Index<PatId> for InferenceResult {
187#[derive(Clone, Debug)] 186#[derive(Clone, Debug)]
188struct InferenceContext<'a, D: HirDatabase> { 187struct InferenceContext<'a, D: HirDatabase> {
189 db: &'a D, 188 db: &'a D,
189 owner: DefWithBody,
190 body: Arc<Body>, 190 body: Arc<Body>,
191 resolver: Resolver, 191 resolver: Resolver,
192 var_unification_table: InPlaceUnificationTable<TypeVarId>, 192 var_unification_table: InPlaceUnificationTable<TypeVarId>,
@@ -204,7 +204,7 @@ struct InferenceContext<'a, D: HirDatabase> {
204} 204}
205 205
206impl<'a, D: HirDatabase> InferenceContext<'a, D> { 206impl<'a, D: HirDatabase> InferenceContext<'a, D> {
207 fn new(db: &'a D, body: Arc<Body>, resolver: Resolver) -> Self { 207 fn new(db: &'a D, owner: DefWithBody, resolver: Resolver) -> Self {
208 InferenceContext { 208 InferenceContext {
209 result: InferenceResult::default(), 209 result: InferenceResult::default(),
210 var_unification_table: InPlaceUnificationTable::new(), 210 var_unification_table: InPlaceUnificationTable::new(),
@@ -213,7 +213,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
213 trait_env: lower::trait_env(db, &resolver), 213 trait_env: lower::trait_env(db, &resolver),
214 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), 214 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver),
215 db, 215 db,
216 body, 216 owner,
217 body: db.body(owner),
217 resolver, 218 resolver,
218 } 219 }
219 } 220 }
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index 4af1d65ee..c6802487a 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -130,10 +130,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
130 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 130 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
131 Substs(sig_tys.into()), 131 Substs(sig_tys.into()),
132 ); 132 );
133 let closure_ty = Ty::apply_one( 133 let closure_ty =
134 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, 134 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty);
135 sig_ty,
136 );
137 135
138 // Eagerly try to relate the closure type with the expected 136 // Eagerly try to relate the closure type with the expected
139 // type, otherwise we often won't have enough information to 137 // type, otherwise we often won't have enough information to
@@ -184,7 +182,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
184 } 182 }
185 Expr::Path(p) => { 183 Expr::Path(p) => {
186 // FIXME this could be more efficient... 184 // FIXME this could be more efficient...
187 let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); 185 let resolver = expr::resolver_for_expr(self.db, self.owner, tgt_expr);
188 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) 186 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
189 } 187 }
190 Expr::Continue => Ty::simple(TypeCtor::Never), 188 Expr::Continue => Ty::simple(TypeCtor::Never),
@@ -452,8 +450,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
452 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) 450 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type)
453 } 451 }
454 Literal::Char(..) => Ty::simple(TypeCtor::Char), 452 Literal::Char(..) => Ty::simple(TypeCtor::Char),
455 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)), 453 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())),
456 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)), 454 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float((*ty).into())),
457 }, 455 },
458 }; 456 };
459 // use a new type variable if we got Ty::Unknown here 457 // use a new type variable if we got Ty::Unknown here
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 52d24e24d..1832fcf50 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -25,7 +25,7 @@ use crate::{
25 generics::{GenericDef, WherePredicate}, 25 generics::{GenericDef, WherePredicate},
26 resolve::{Resolver, TypeNs}, 26 resolve::{Resolver, TypeNs},
27 ty::{ 27 ty::{
28 primitive::{FloatTy, IntTy}, 28 primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
29 Adt, 29 Adt,
30 }, 30 },
31 util::make_mut_slice, 31 util::make_mut_slice,
@@ -657,13 +657,41 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
657 BuiltinType::Char => TypeCtor::Char, 657 BuiltinType::Char => TypeCtor::Char,
658 BuiltinType::Bool => TypeCtor::Bool, 658 BuiltinType::Bool => TypeCtor::Bool,
659 BuiltinType::Str => TypeCtor::Str, 659 BuiltinType::Str => TypeCtor::Str,
660 BuiltinType::Int(BuiltinInt { signedness, bitness }) => { 660 BuiltinType::Int(t) => TypeCtor::Int(IntTy::from(t).into()),
661 TypeCtor::Int(IntTy { signedness, bitness }.into()) 661 BuiltinType::Float(t) => TypeCtor::Float(FloatTy::from(t).into()),
662 }
663 BuiltinType::Float(BuiltinFloat { bitness }) => TypeCtor::Float(FloatTy { bitness }.into()),
664 }) 662 })
665} 663}
666 664
665impl From<BuiltinInt> for IntTy {
666 fn from(t: BuiltinInt) -> Self {
667 IntTy { signedness: t.signedness, bitness: t.bitness }
668 }
669}
670
671impl From<BuiltinFloat> for FloatTy {
672 fn from(t: BuiltinFloat) -> Self {
673 FloatTy { bitness: t.bitness }
674 }
675}
676
677impl From<Option<BuiltinInt>> for UncertainIntTy {
678 fn from(t: Option<BuiltinInt>) -> Self {
679 match t {
680 None => UncertainIntTy::Unknown,
681 Some(t) => UncertainIntTy::Known(t.into()),
682 }
683 }
684}
685
686impl From<Option<BuiltinFloat>> for UncertainFloatTy {
687 fn from(t: Option<BuiltinFloat>) -> Self {
688 match t {
689 None => UncertainFloatTy::Unknown,
690 Some(t) => UncertainFloatTy::Known(t.into()),
691 }
692 }
693}
694
667fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { 695fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
668 let struct_data = db.struct_data(def.id.into()); 696 let struct_data = db.struct_data(def.id.into());
669 let fields = match struct_data.variant_data.fields() { 697 let fields = match struct_data.variant_data.fields() {
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 1749752f1..7362de4c3 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -129,24 +129,6 @@ impl IntTy {
129 (Signedness::Unsigned, IntBitness::X128) => "u128", 129 (Signedness::Unsigned, IntBitness::X128) => "u128",
130 } 130 }
131 } 131 }
132
133 pub(crate) fn from_suffix(suffix: &str) -> Option<IntTy> {
134 match suffix {
135 "isize" => Some(IntTy::isize()),
136 "i8" => Some(IntTy::i8()),
137 "i16" => Some(IntTy::i16()),
138 "i32" => Some(IntTy::i32()),
139 "i64" => Some(IntTy::i64()),
140 "i128" => Some(IntTy::i128()),
141 "usize" => Some(IntTy::usize()),
142 "u8" => Some(IntTy::u8()),
143 "u16" => Some(IntTy::u16()),
144 "u32" => Some(IntTy::u32()),
145 "u64" => Some(IntTy::u64()),
146 "u128" => Some(IntTy::u128()),
147 _ => None,
148 }
149 }
150} 132}
151 133
152#[derive(Copy, Clone, PartialEq, Eq, Hash)] 134#[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -181,12 +163,4 @@ impl FloatTy {
181 FloatBitness::X64 => "f64", 163 FloatBitness::X64 => "f64",
182 } 164 }
183 } 165 }
184
185 pub(crate) fn from_suffix(suffix: &str) -> Option<FloatTy> {
186 match suffix {
187 "f32" => Some(FloatTy::f32()),
188 "f64" => Some(FloatTy::f64()),
189 _ => None,
190 }
191 }
192} 166}
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
new file mode 100644
index 000000000..7447904ea
--- /dev/null
+++ b/crates/ra_hir_def/src/body.rs
@@ -0,0 +1,2 @@
1//! FIXME: write short doc here
2mod lower;
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
new file mode 100644
index 000000000..1a144b1f9
--- /dev/null
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -0,0 +1,49 @@
1//! FIXME: write short doc here
2
3use ra_syntax::ast;
4
5use crate::expr::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering};
6
7impl From<ast::BinOp> for BinaryOp {
8 fn from(ast_op: ast::BinOp) -> Self {
9 match ast_op {
10 ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
11 ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
12 ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
13 ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
14 ast::BinOp::LesserEqualTest => {
15 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
16 }
17 ast::BinOp::GreaterEqualTest => {
18 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
19 }
20 ast::BinOp::LesserTest => {
21 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
22 }
23 ast::BinOp::GreaterTest => {
24 BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
25 }
26 ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
27 ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
28 ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
29 ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
30 ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
31 ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
32 ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
33 ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
34 ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
35 ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
36 ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
37 ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
38 ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
39 ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
40 ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
41 ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
42 ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
43 ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
44 ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
45 ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
46 ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
47 }
48 }
49}
diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs
index 996e86fd9..5e8157144 100644
--- a/crates/ra_hir_def/src/builtin_type.rs
+++ b/crates/ra_hir_def/src/builtin_type.rs
@@ -56,22 +56,22 @@ impl BuiltinType {
56 (name::BOOL, BuiltinType::Bool), 56 (name::BOOL, BuiltinType::Bool),
57 (name::STR, BuiltinType::Str ), 57 (name::STR, BuiltinType::Str ),
58 58
59 (name::ISIZE, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize })), 59 (name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)),
60 (name::I8, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 })), 60 (name::I8, BuiltinType::Int(BuiltinInt::I8)),
61 (name::I16, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 })), 61 (name::I16, BuiltinType::Int(BuiltinInt::I16)),
62 (name::I32, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 })), 62 (name::I32, BuiltinType::Int(BuiltinInt::I32)),
63 (name::I64, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 })), 63 (name::I64, BuiltinType::Int(BuiltinInt::I64)),
64 (name::I128, BuiltinType::Int(BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 })), 64 (name::I128, BuiltinType::Int(BuiltinInt::I128)),
65 65
66 (name::USIZE, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize })), 66 (name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)),
67 (name::U8, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 })), 67 (name::U8, BuiltinType::Int(BuiltinInt::U8)),
68 (name::U16, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 })), 68 (name::U16, BuiltinType::Int(BuiltinInt::U16)),
69 (name::U32, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 })), 69 (name::U32, BuiltinType::Int(BuiltinInt::U32)),
70 (name::U64, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 })), 70 (name::U64, BuiltinType::Int(BuiltinInt::U64)),
71 (name::U128, BuiltinType::Int(BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 })), 71 (name::U128, BuiltinType::Int(BuiltinInt::U128)),
72 72
73 (name::F32, BuiltinType::Float(BuiltinFloat { bitness: FloatBitness::X32 })), 73 (name::F32, BuiltinType::Float(BuiltinFloat::F32)),
74 (name::F64, BuiltinType::Float(BuiltinFloat { bitness: FloatBitness::X64 })), 74 (name::F64, BuiltinType::Float(BuiltinFloat::F64)),
75 ]; 75 ];
76} 76}
77 77
@@ -104,3 +104,57 @@ impl fmt::Display for BuiltinType {
104 f.write_str(type_name) 104 f.write_str(type_name)
105 } 105 }
106} 106}
107
108#[rustfmt::skip]
109impl BuiltinInt {
110 pub const ISIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::Xsize };
111 pub const I8 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X8 };
112 pub const I16 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X16 };
113 pub const I32 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X32 };
114 pub const I64 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X64 };
115 pub const I128 : BuiltinInt = BuiltinInt { signedness: Signedness::Signed, bitness: IntBitness::X128 };
116
117 pub const USIZE: BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize };
118 pub const U8 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X8 };
119 pub const U16 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X16 };
120 pub const U32 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X32 };
121 pub const U64 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X64 };
122 pub const U128 : BuiltinInt = BuiltinInt { signedness: Signedness::Unsigned, bitness: IntBitness::X128 };
123
124
125 pub fn from_suffix(suffix: &str) -> Option<BuiltinInt> {
126 let res = match suffix {
127 "isize" => Self::ISIZE,
128 "i8" => Self::I8,
129 "i16" => Self::I16,
130 "i32" => Self::I32,
131 "i64" => Self::I64,
132 "i128" => Self::I128,
133
134 "usize" => Self::USIZE,
135 "u8" => Self::U8,
136 "u16" => Self::U16,
137 "u32" => Self::U32,
138 "u64" => Self::U64,
139 "u128" => Self::U128,
140
141 _ => return None,
142 };
143 Some(res)
144 }
145}
146
147#[rustfmt::skip]
148impl BuiltinFloat {
149 pub const F32: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X32 };
150 pub const F64: BuiltinFloat = BuiltinFloat { bitness: FloatBitness::X64 };
151
152 pub fn from_suffix(suffix: &str) -> Option<BuiltinFloat> {
153 let res = match suffix {
154 "f32" => BuiltinFloat::F32,
155 "f64" => BuiltinFloat::F64,
156 _ => return None,
157 };
158 Some(res)
159 }
160}
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
new file mode 100644
index 000000000..12eb0da68
--- /dev/null
+++ b/crates/ra_hir_def/src/expr.rs
@@ -0,0 +1,419 @@
1//! This module describes hir-level representation of expressions.
2//!
3//! This representaion is:
4//!
5//! 1. Identity-based. Each expression has an `id`, so we can distinguish
6//! between different `1` in `1 + 1`.
7//! 2. Independent of syntax. Though syntactic provenance information can be
8//! attached separately via id-based side map.
9//! 3. Unresolved. Paths are stored as sequences of names, and not as defs the
10//! names refer to.
11//! 4. Desugared. There's no `if let`.
12
13use hir_expand::name::Name;
14use ra_arena::{impl_arena_id, RawId};
15
16use crate::{
17 builtin_type::{BuiltinFloat, BuiltinInt},
18 path::{GenericArgs, Path},
19 type_ref::{Mutability, TypeRef},
20};
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct ExprId(RawId);
24impl_arena_id!(ExprId);
25
26impl ExprId {
27 pub fn dummy() -> ExprId {
28 ExprId((!0).into())
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub struct PatId(RawId);
34impl_arena_id!(PatId);
35
36#[derive(Debug, Clone, Eq, PartialEq)]
37pub enum Literal {
38 String(String),
39 ByteString(Vec<u8>),
40 Char(char),
41 Bool(bool),
42 Int(u64, Option<BuiltinInt>),
43 Float(u64, Option<BuiltinFloat>), // FIXME: f64 is not Eq
44}
45
46#[derive(Debug, Clone, Eq, PartialEq)]
47pub enum Expr {
48 /// This is produced if syntax tree does not have a required expression piece.
49 Missing,
50 Path(Path),
51 If {
52 condition: ExprId,
53 then_branch: ExprId,
54 else_branch: Option<ExprId>,
55 },
56 Block {
57 statements: Vec<Statement>,
58 tail: Option<ExprId>,
59 },
60 Loop {
61 body: ExprId,
62 },
63 While {
64 condition: ExprId,
65 body: ExprId,
66 },
67 For {
68 iterable: ExprId,
69 pat: PatId,
70 body: ExprId,
71 },
72 Call {
73 callee: ExprId,
74 args: Vec<ExprId>,
75 },
76 MethodCall {
77 receiver: ExprId,
78 method_name: Name,
79 args: Vec<ExprId>,
80 generic_args: Option<GenericArgs>,
81 },
82 Match {
83 expr: ExprId,
84 arms: Vec<MatchArm>,
85 },
86 Continue,
87 Break {
88 expr: Option<ExprId>,
89 },
90 Return {
91 expr: Option<ExprId>,
92 },
93 RecordLit {
94 path: Option<Path>,
95 fields: Vec<RecordLitField>,
96 spread: Option<ExprId>,
97 },
98 Field {
99 expr: ExprId,
100 name: Name,
101 },
102 Await {
103 expr: ExprId,
104 },
105 Try {
106 expr: ExprId,
107 },
108 TryBlock {
109 body: ExprId,
110 },
111 Cast {
112 expr: ExprId,
113 type_ref: TypeRef,
114 },
115 Ref {
116 expr: ExprId,
117 mutability: Mutability,
118 },
119 Box {
120 expr: ExprId,
121 },
122 UnaryOp {
123 expr: ExprId,
124 op: UnaryOp,
125 },
126 BinaryOp {
127 lhs: ExprId,
128 rhs: ExprId,
129 op: Option<BinaryOp>,
130 },
131 Index {
132 base: ExprId,
133 index: ExprId,
134 },
135 Lambda {
136 args: Vec<PatId>,
137 arg_types: Vec<Option<TypeRef>>,
138 body: ExprId,
139 },
140 Tuple {
141 exprs: Vec<ExprId>,
142 },
143 Array(Array),
144 Literal(Literal),
145}
146
147#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
148pub enum BinaryOp {
149 LogicOp(LogicOp),
150 ArithOp(ArithOp),
151 CmpOp(CmpOp),
152 Assignment { op: Option<ArithOp> },
153}
154
155#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
156pub enum LogicOp {
157 And,
158 Or,
159}
160
161#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
162pub enum CmpOp {
163 Eq { negated: bool },
164 Ord { ordering: Ordering, strict: bool },
165}
166
167#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
168pub enum Ordering {
169 Less,
170 Greater,
171}
172
173#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
174pub enum ArithOp {
175 Add,
176 Mul,
177 Sub,
178 Div,
179 Rem,
180 Shl,
181 Shr,
182 BitXor,
183 BitOr,
184 BitAnd,
185}
186
187pub use ra_syntax::ast::PrefixOp as UnaryOp;
188#[derive(Debug, Clone, Eq, PartialEq)]
189pub enum Array {
190 ElementList(Vec<ExprId>),
191 Repeat { initializer: ExprId, repeat: ExprId },
192}
193
194#[derive(Debug, Clone, Eq, PartialEq)]
195pub struct MatchArm {
196 pub pats: Vec<PatId>,
197 pub guard: Option<ExprId>,
198 pub expr: ExprId,
199}
200
201#[derive(Debug, Clone, Eq, PartialEq)]
202pub struct RecordLitField {
203 pub name: Name,
204 pub expr: ExprId,
205}
206
207#[derive(Debug, Clone, Eq, PartialEq)]
208pub enum Statement {
209 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> },
210 Expr(ExprId),
211}
212
213impl Expr {
214 pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
215 match self {
216 Expr::Missing => {}
217 Expr::Path(_) => {}
218 Expr::If { condition, then_branch, else_branch } => {
219 f(*condition);
220 f(*then_branch);
221 if let Some(else_branch) = else_branch {
222 f(*else_branch);
223 }
224 }
225 Expr::Block { statements, tail } => {
226 for stmt in statements {
227 match stmt {
228 Statement::Let { initializer, .. } => {
229 if let Some(expr) = initializer {
230 f(*expr);
231 }
232 }
233 Statement::Expr(e) => f(*e),
234 }
235 }
236 if let Some(expr) = tail {
237 f(*expr);
238 }
239 }
240 Expr::TryBlock { body } => f(*body),
241 Expr::Loop { body } => f(*body),
242 Expr::While { condition, body } => {
243 f(*condition);
244 f(*body);
245 }
246 Expr::For { iterable, body, .. } => {
247 f(*iterable);
248 f(*body);
249 }
250 Expr::Call { callee, args } => {
251 f(*callee);
252 for arg in args {
253 f(*arg);
254 }
255 }
256 Expr::MethodCall { receiver, args, .. } => {
257 f(*receiver);
258 for arg in args {
259 f(*arg);
260 }
261 }
262 Expr::Match { expr, arms } => {
263 f(*expr);
264 for arm in arms {
265 f(arm.expr);
266 }
267 }
268 Expr::Continue => {}
269 Expr::Break { expr } | Expr::Return { expr } => {
270 if let Some(expr) = expr {
271 f(*expr);
272 }
273 }
274 Expr::RecordLit { fields, spread, .. } => {
275 for field in fields {
276 f(field.expr);
277 }
278 if let Some(expr) = spread {
279 f(*expr);
280 }
281 }
282 Expr::Lambda { body, .. } => {
283 f(*body);
284 }
285 Expr::BinaryOp { lhs, rhs, .. } => {
286 f(*lhs);
287 f(*rhs);
288 }
289 Expr::Index { base, index } => {
290 f(*base);
291 f(*index);
292 }
293 Expr::Field { expr, .. }
294 | Expr::Await { expr }
295 | Expr::Try { expr }
296 | Expr::Cast { expr, .. }
297 | Expr::Ref { expr, .. }
298 | Expr::UnaryOp { expr, .. }
299 | Expr::Box { expr } => {
300 f(*expr);
301 }
302 Expr::Tuple { exprs } => {
303 for expr in exprs {
304 f(*expr);
305 }
306 }
307 Expr::Array(a) => match a {
308 Array::ElementList(exprs) => {
309 for expr in exprs {
310 f(*expr);
311 }
312 }
313 Array::Repeat { initializer, repeat } => {
314 f(*initializer);
315 f(*repeat)
316 }
317 },
318 Expr::Literal(_) => {}
319 }
320 }
321}
322
323/// Explicit binding annotations given in the HIR for a binding. Note
324/// that this is not the final binding *mode* that we infer after type
325/// inference.
326#[derive(Clone, PartialEq, Eq, Debug, Copy)]
327pub enum BindingAnnotation {
328 /// No binding annotation given: this means that the final binding mode
329 /// will depend on whether we have skipped through a `&` reference
330 /// when matching. For example, the `x` in `Some(x)` will have binding
331 /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
332 /// ultimately be inferred to be by-reference.
333 Unannotated,
334
335 /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
336 Mutable,
337
338 /// Annotated as `ref`, like `ref x`
339 Ref,
340
341 /// Annotated as `ref mut x`.
342 RefMut,
343}
344
345impl BindingAnnotation {
346 pub fn new(is_mutable: bool, is_ref: bool) -> Self {
347 match (is_mutable, is_ref) {
348 (true, true) => BindingAnnotation::RefMut,
349 (false, true) => BindingAnnotation::Ref,
350 (true, false) => BindingAnnotation::Mutable,
351 (false, false) => BindingAnnotation::Unannotated,
352 }
353 }
354}
355
356#[derive(Debug, Clone, Eq, PartialEq)]
357pub struct RecordFieldPat {
358 pub name: Name,
359 pub pat: PatId,
360}
361
362/// Close relative to rustc's hir::PatKind
363#[derive(Debug, Clone, Eq, PartialEq)]
364pub enum Pat {
365 Missing,
366 Wild,
367 Tuple(Vec<PatId>),
368 Record {
369 path: Option<Path>,
370 args: Vec<RecordFieldPat>,
371 // FIXME: 'ellipsis' option
372 },
373 Range {
374 start: ExprId,
375 end: ExprId,
376 },
377 Slice {
378 prefix: Vec<PatId>,
379 rest: Option<PatId>,
380 suffix: Vec<PatId>,
381 },
382 Path(Path),
383 Lit(ExprId),
384 Bind {
385 mode: BindingAnnotation,
386 name: Name,
387 subpat: Option<PatId>,
388 },
389 TupleStruct {
390 path: Option<Path>,
391 args: Vec<PatId>,
392 },
393 Ref {
394 pat: PatId,
395 mutability: Mutability,
396 },
397}
398
399impl Pat {
400 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
401 match self {
402 Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {}
403 Pat::Bind { subpat, .. } => {
404 subpat.iter().copied().for_each(f);
405 }
406 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => {
407 args.iter().copied().for_each(f);
408 }
409 Pat::Ref { pat, .. } => f(*pat),
410 Pat::Slice { prefix, rest, suffix } => {
411 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
412 total_iter.copied().for_each(f);
413 }
414 Pat::Record { args, .. } => {
415 args.iter().map(|f| f.pat).for_each(f);
416 }
417 }
418 }
419}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 239317efe..4a758bb83 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -14,6 +14,8 @@ pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt; 15pub mod adt;
16pub mod diagnostics; 16pub mod diagnostics;
17pub mod expr;
18pub mod body;
17 19
18#[cfg(test)] 20#[cfg(test)]
19mod test_db; 21mod test_db;
diff --git a/xtask/tests/tidy-tests/docs.rs b/xtask/tests/tidy-tests/docs.rs
index 227937f46..141219860 100644
--- a/xtask/tests/tidy-tests/docs.rs
+++ b/xtask/tests/tidy-tests/docs.rs
@@ -1,10 +1,6 @@
1use std::fs; 1use std::{collections::HashMap, fs, io::prelude::*, io::BufReader, path::Path};
2use std::io::prelude::*;
3use std::io::BufReader;
4use std::path::Path;
5 2
6use walkdir::{DirEntry, WalkDir}; 3use walkdir::{DirEntry, WalkDir};
7
8use xtask::project_root; 4use xtask::project_root;
9 5
10fn is_exclude_dir(p: &Path) -> bool { 6fn is_exclude_dir(p: &Path) -> bool {
@@ -37,6 +33,7 @@ fn no_docs_comments() {
37 let crates = project_root().join("crates"); 33 let crates = project_root().join("crates");
38 let iter = WalkDir::new(crates); 34 let iter = WalkDir::new(crates);
39 let mut missing_docs = Vec::new(); 35 let mut missing_docs = Vec::new();
36 let mut contains_fixme = Vec::new();
40 for f in iter.into_iter().filter_entry(|e| !is_hidden(e)) { 37 for f in iter.into_iter().filter_entry(|e| !is_hidden(e)) {
41 let f = f.unwrap(); 38 let f = f.unwrap();
42 if f.file_type().is_dir() { 39 if f.file_type().is_dir() {
@@ -54,7 +51,12 @@ fn no_docs_comments() {
54 let mut reader = BufReader::new(fs::File::open(f.path()).unwrap()); 51 let mut reader = BufReader::new(fs::File::open(f.path()).unwrap());
55 let mut line = String::new(); 52 let mut line = String::new();
56 reader.read_line(&mut line).unwrap(); 53 reader.read_line(&mut line).unwrap();
57 if !line.starts_with("//!") { 54
55 if line.starts_with("//!") {
56 if line.contains("FIXME") {
57 contains_fixme.push(f.path().to_path_buf())
58 }
59 } else {
58 missing_docs.push(f.path().display().to_string()); 60 missing_docs.push(f.path().display().to_string());
59 } 61 }
60 } 62 }
@@ -65,4 +67,39 @@ fn no_docs_comments() {
65 missing_docs.join("\n") 67 missing_docs.join("\n")
66 ) 68 )
67 } 69 }
70
71 let whitelist = [
72 "ra_batch",
73 "ra_cli",
74 "ra_db",
75 "ra_hir",
76 "ra_hir_expand",
77 "ra_hir_def",
78 "ra_ide_api",
79 "ra_lsp_server",
80 "ra_mbe",
81 "ra_parser",
82 "ra_prof",
83 "ra_project_model",
84 "ra_syntax",
85 "ra_text_edit",
86 "ra_tt",
87 ];
88
89 let mut has_fixmes = whitelist.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>();
90 'outer: for path in contains_fixme {
91 for krate in whitelist.iter() {
92 if path.components().any(|it| it.as_os_str() == *krate) {
93 has_fixmes.insert(krate, true);
94 continue 'outer;
95 }
96 }
97 panic!("FIXME doc in a fully-documented crate: {}", path.display())
98 }
99
100 for (krate, has_fixme) in has_fixmes.iter() {
101 if !has_fixme {
102 panic!("crate {} is fully documented, remove it from the white list", krate)
103 }
104 }
68} 105}