aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty.rs40
-rw-r--r--crates/ra_hir/src/ty/tests.rs12
-rw-r--r--crates/ra_hir/src/ty/tests/data/bug_484.txt5
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs7
-rw-r--r--crates/ra_lsp_server/src/project_model/sysroot.rs8
-rw-r--r--crates/ra_syntax/src/grammar/items/nominal.rs10
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.rs4
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.txt39
-rw-r--r--crates/tools/src/main.rs4
-rw-r--r--editors/README.md2
11 files changed, 120 insertions, 13 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 0c24a0652..2d533eb6a 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -18,6 +18,7 @@ mod primitive;
18#[cfg(test)] 18#[cfg(test)]
19mod tests; 19mod tests;
20 20
21use std::borrow::Cow;
21use std::ops::Index; 22use std::ops::Index;
22use std::sync::Arc; 23use std::sync::Arc;
23use std::{fmt, mem}; 24use std::{fmt, mem};
@@ -671,7 +672,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
671 } 672 }
672 673
673 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 674 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
674 match (ty1, ty2) { 675 // try to resolve type vars first
676 let ty1 = self.resolve_ty_shallow(ty1);
677 let ty2 = self.resolve_ty_shallow(ty2);
678 match (&*ty1, &*ty2) {
675 (Ty::Unknown, ..) => true, 679 (Ty::Unknown, ..) => true,
676 (.., Ty::Unknown) => true, 680 (.., Ty::Unknown) => true,
677 (Ty::Bool, _) 681 (Ty::Bool, _)
@@ -698,10 +702,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
698 .zip(ts2.iter()) 702 .zip(ts2.iter())
699 .all(|(t1, t2)| self.unify(t1, t2)), 703 .all(|(t1, t2)| self.unify(t1, t2)),
700 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => { 704 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => {
705 // both type vars are unknown since we tried to resolve them
701 self.var_unification_table.union(*tv1, *tv2); 706 self.var_unification_table.union(*tv1, *tv2);
702 true 707 true
703 } 708 }
704 (Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => { 709 (Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => {
710 // the type var is unknown since we tried to resolve it
705 self.var_unification_table 711 self.var_unification_table
706 .union_value(*tv, TypeVarValue::Known(other.clone())); 712 .union_value(*tv, TypeVarValue::Known(other.clone()));
707 true 713 true
@@ -746,6 +752,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
746 }) 752 })
747 } 753 }
748 754
755 /// If `ty` is a type variable with known type, returns that type;
756 /// otherwise, return ty.
757 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
758 match ty {
759 Ty::Infer(InferTy::TypeVar(tv)) => {
760 match self.var_unification_table.probe_value(*tv).known() {
761 Some(known_ty) => {
762 // The known_ty can't be a type var itself
763 Cow::Owned(known_ty.clone())
764 }
765 _ => Cow::Borrowed(ty),
766 }
767 }
768 _ => Cow::Borrowed(ty),
769 }
770 }
771
749 /// Resolves the type completely; type variables without known type are 772 /// Resolves the type completely; type variables without known type are
750 /// replaced by Ty::Unknown. 773 /// replaced by Ty::Unknown.
751 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 774 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
@@ -816,12 +839,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
816 // if let is desugared to match, so this is always simple if 839 // if let is desugared to match, so this is always simple if
817 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 840 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?;
818 let then_ty = self.infer_expr(*then_branch, expected)?; 841 let then_ty = self.infer_expr(*then_branch, expected)?;
819 if let Some(else_branch) = else_branch { 842 match else_branch {
820 self.infer_expr(*else_branch, expected)?; 843 Some(else_branch) => {
821 } else { 844 self.infer_expr(*else_branch, expected)?;
822 // no else branch -> unit 845 }
823 self.unify(&expected.ty, &Ty::unit()); // actually coerce 846 None => {
824 } 847 // no else branch -> unit
848 self.unify(&then_ty, &Ty::unit()); // actually coerce
849 }
850 };
825 then_ty 851 then_ty
826 } 852 }
827 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected)?, 853 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected)?,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index d8c0af326..815aecda7 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -230,6 +230,18 @@ fn test2(a1: *const A, a2: *mut A) {
230 ); 230 );
231} 231}
232 232
233#[test]
234fn infer_bug_484() {
235 check_inference(
236 r#"
237fn test() {
238 let x = if true {};
239}
240"#,
241 "bug_484.txt",
242 );
243}
244
233fn infer(content: &str) -> String { 245fn infer(content: &str) -> String {
234 let (db, _, file_id) = MockDatabase::with_single_file(content); 246 let (db, _, file_id) = MockDatabase::with_single_file(content);
235 let source_file = db.source_file(file_id); 247 let source_file = db.source_file(file_id);
diff --git a/crates/ra_hir/src/ty/tests/data/bug_484.txt b/crates/ra_hir/src/ty/tests/data/bug_484.txt
new file mode 100644
index 000000000..300530551
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/bug_484.txt
@@ -0,0 +1,5 @@
1[11; 37) '{ l... {}; }': ()
2[20; 21) 'x': ()
3[24; 34) 'if true {}': ()
4[27; 31) 'true': bool
5[32; 34) '{}': ()
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 726c758aa..03c834dbc 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -65,7 +65,7 @@ pub fn main_loop(
65 let workspaces = match ws_worker.recv().unwrap() { 65 let workspaces = match ws_worker.recv().unwrap() {
66 Ok(ws) => vec![ws], 66 Ok(ws) => vec![ws],
67 Err(e) => { 67 Err(e) => {
68 log::warn!("loading workspace failed: {}", e); 68 log::error!("loading workspace failed: {}", e);
69 Vec::new() 69 Vec::new()
70 } 70 }
71 }; 71 };
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 7f6146b6c..a781df181 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -4,7 +4,7 @@ use gen_lsp_server::ErrorCode;
4use languageserver_types::{ 4use languageserver_types::{
5 CodeActionResponse, Command, CodeLens, Diagnostic, DiagnosticSeverity, DocumentFormattingParams, 5 CodeActionResponse, Command, CodeLens, Diagnostic, DiagnosticSeverity, DocumentFormattingParams,
6 DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, 6 DocumentHighlight, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
7 FoldingRangeParams, Hover, HoverContents, Location, MarkedString, MarkupContent, MarkupKind, 7 FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind,
8 ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, RenameParams, 8 ParameterInformation, ParameterLabel, Position, PrepareRenameResponse, Range, RenameParams,
9 SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, 9 SignatureInformation, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit,
10}; 10};
@@ -422,7 +422,10 @@ pub fn handle_hover(
422 let line_index = world.analysis.file_line_index(position.file_id); 422 let line_index = world.analysis.file_line_index(position.file_id);
423 let range = info.range.conv_with(&line_index); 423 let range = info.range.conv_with(&line_index);
424 let res = Hover { 424 let res = Hover {
425 contents: HoverContents::Scalar(MarkedString::String(info.info)), 425 contents: HoverContents::Markup(MarkupContent {
426 kind: MarkupKind::Markdown,
427 value: info.info,
428 }),
426 range: Some(range), 429 range: Some(range),
427 }; 430 };
428 Ok(Some(res)) 431 Ok(Some(res))
diff --git a/crates/ra_lsp_server/src/project_model/sysroot.rs b/crates/ra_lsp_server/src/project_model/sysroot.rs
index 1dbab57f8..3b2fa070b 100644
--- a/crates/ra_lsp_server/src/project_model/sysroot.rs
+++ b/crates/ra_lsp_server/src/project_model/sysroot.rs
@@ -44,6 +44,14 @@ impl Sysroot {
44 let stdout = String::from_utf8(rustc_output.stdout)?; 44 let stdout = String::from_utf8(rustc_output.stdout)?;
45 let sysroot_path = Path::new(stdout.trim()); 45 let sysroot_path = Path::new(stdout.trim());
46 let src = sysroot_path.join("lib/rustlib/src/rust/src"); 46 let src = sysroot_path.join("lib/rustlib/src/rust/src");
47 if !src.exists() {
48 failure::bail!(
49 "can't load standard library from sysroot\n\
50 {:?}\n\
51 try running `rustup component add rust-src`",
52 src,
53 );
54 }
47 55
48 let mut sysroot = Sysroot { 56 let mut sysroot = Sysroot {
49 crates: Arena::default(), 57 crates: Arena::default(),
diff --git a/crates/ra_syntax/src/grammar/items/nominal.rs b/crates/ra_syntax/src/grammar/items/nominal.rs
index 495462ca7..0784fb7b1 100644
--- a/crates/ra_syntax/src/grammar/items/nominal.rs
+++ b/crates/ra_syntax/src/grammar/items/nominal.rs
@@ -140,6 +140,16 @@ fn pos_field_list(p: &mut Parser) {
140 } 140 }
141 while !p.at(R_PAREN) && !p.at(EOF) { 141 while !p.at(R_PAREN) && !p.at(EOF) {
142 let m = p.start(); 142 let m = p.start();
143 // test pos_field_attrs
144 // struct S (
145 // #[serde(with = "url_serde")]
146 // pub Uri,
147 // );
148 //
149 // enum S {
150 // Uri(#[serde(with = "url_serde")] Uri),
151 // }
152 attributes::outer_attributes(p);
143 opt_visibility(p); 153 opt_visibility(p);
144 if !p.at_ts(types::TYPE_FIRST) { 154 if !p.at_ts(types::TYPE_FIRST) {
145 p.error("expected a type"); 155 p.error("expected a type");
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.rs
new file mode 100644
index 000000000..635b9ac21
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.rs
@@ -0,0 +1,4 @@
1struct S (
2 #[serde(with = "url_serde")]
3 pub Uri,
4);
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.txt
new file mode 100644
index 000000000..99ec0755b
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0115_pos_field_attrs.txt
@@ -0,0 +1,39 @@
1SOURCE_FILE@[0; 60)
2 STRUCT_DEF@[0; 59)
3 STRUCT_KW@[0; 6)
4 WHITESPACE@[6; 7)
5 NAME@[7; 8)
6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9)
8 POS_FIELD_LIST@[9; 58)
9 L_PAREN@[9; 10)
10 WHITESPACE@[10; 15)
11 POS_FIELD@[15; 55)
12 ATTR@[15; 43)
13 POUND@[15; 16)
14 TOKEN_TREE@[16; 43)
15 L_BRACK@[16; 17)
16 IDENT@[17; 22) "serde"
17 TOKEN_TREE@[22; 42)
18 L_PAREN@[22; 23)
19 IDENT@[23; 27) "with"
20 WHITESPACE@[27; 28)
21 EQ@[28; 29)
22 WHITESPACE@[29; 30)
23 STRING@[30; 41)
24 R_PAREN@[41; 42)
25 R_BRACK@[42; 43)
26 WHITESPACE@[43; 48)
27 VISIBILITY@[48; 51)
28 PUB_KW@[48; 51)
29 WHITESPACE@[51; 52)
30 PATH_TYPE@[52; 55)
31 PATH@[52; 55)
32 PATH_SEGMENT@[52; 55)
33 NAME_REF@[52; 55)
34 IDENT@[52; 55) "Uri"
35 COMMA@[55; 56)
36 WHITESPACE@[56; 57)
37 R_PAREN@[57; 58)
38 SEMI@[58; 59)
39 WHITESPACE@[59; 60)
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs
index 9d73d57c4..5597aae5a 100644
--- a/crates/tools/src/main.rs
+++ b/crates/tools/src/main.rs
@@ -158,12 +158,12 @@ fn install_code_extension() -> Result<()> {
158 } 158 }
159 if cfg!(windows) { 159 if cfg!(windows) {
160 run( 160 run(
161 r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix", 161 r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix --force",
162 "./editors/code", 162 "./editors/code",
163 )?; 163 )?;
164 } else { 164 } else {
165 run( 165 run(
166 r"code --install-extension ./ra-lsp-0.0.1.vsix", 166 r"code --install-extension ./ra-lsp-0.0.1.vsix --force",
167 "./editors/code", 167 "./editors/code",
168 )?; 168 )?;
169 } 169 }
diff --git a/editors/README.md b/editors/README.md
index a63ced725..5b09750e6 100644
--- a/editors/README.md
+++ b/editors/README.md
@@ -1,7 +1,7 @@
1To install experimental VS Code plugin: 1To install experimental VS Code plugin:
2 2
3``` 3```
4$ git clone https://github.com/rust-analyzer/rust-analyzer.git 4$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
5$ cd rust-analyzer 5$ cd rust-analyzer
6$ cargo install-code 6$ cargo install-code
7``` 7```