aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/actions/github-release/main.js2
-rw-r--r--.github/workflows/ci.yaml17
-rw-r--r--.github/workflows/release.yaml5
-rw-r--r--.gitignore4
-rw-r--r--.vscode/launch.json34
-rw-r--r--.vscode/tasks.json12
-rw-r--r--Cargo.lock118
-rw-r--r--Cargo.toml2
-rw-r--r--README.md8
-rw-r--r--bors.toml4
-rw-r--r--crates/ra_assists/src/handlers/add_from_impl_for_enum.rs4
-rw-r--r--crates/ra_assists/src/handlers/introduce_named_lifetime.rs303
-rw-r--r--crates/ra_assists/src/handlers/reorder_fields.rs2
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/tests/generated.rs44
-rw-r--r--crates/ra_cfg/src/cfg_expr.rs10
-rw-r--r--crates/ra_db/src/fixture.rs70
-rw-r--r--crates/ra_db/src/input.rs15
-rw-r--r--crates/ra_hir/src/code_model.rs27
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir_def/src/attr.rs10
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/body/lower.rs87
-rw-r--r--crates/ra_hir_def/src/body/scope.rs4
-rw-r--r--crates/ra_hir_def/src/data.rs6
-rw-r--r--crates/ra_hir_def/src/docs.rs50
-rw-r--r--crates/ra_hir_def/src/expr.rs22
-rw-r--r--crates/ra_hir_def/src/lang_item.rs2
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs2
-rw-r--r--crates/ra_hir_def/src/type_ref.rs16
-rw-r--r--crates/ra_hir_expand/src/name.rs6
-rw-r--r--crates/ra_hir_expand/src/proc_macro.rs2
-rw-r--r--crates/ra_hir_ty/Cargo.toml5
-rw-r--r--crates/ra_hir_ty/src/db.rs5
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs4
-rw-r--r--crates/ra_hir_ty/src/infer.rs11
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs98
-rw-r--r--crates/ra_hir_ty/src/lib.rs24
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs17
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs50
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs76
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs118
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs3
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs87
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs14
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs93
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs18
-rw-r--r--crates/ra_ide/src/call_hierarchy.rs29
-rw-r--r--crates/ra_ide/src/completion.rs125
-rw-r--r--crates/ra_ide/src/completion/complete_attribute.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs65
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs61
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs36
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs13
-rw-r--r--crates/ra_ide/src/completion/presentation.rs60
-rw-r--r--crates/ra_ide/src/diagnostics.rs2
-rw-r--r--crates/ra_ide/src/display.rs7
-rw-r--r--crates/ra_ide/src/display/function_signature.rs13
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs66
-rw-r--r--crates/ra_ide/src/display/structure.rs19
-rw-r--r--crates/ra_ide/src/expand_macro.rs11
-rw-r--r--crates/ra_ide/src/extend_selection.rs12
-rw-r--r--crates/ra_ide/src/goto_definition.rs11
-rw-r--r--crates/ra_ide/src/goto_implementation.rs (renamed from crates/ra_ide/src/impls.rs)11
-rw-r--r--crates/ra_ide/src/goto_type_definition.rs11
-rw-r--r--crates/ra_ide/src/hover.rs264
-rw-r--r--crates/ra_ide/src/inlay_hints.rs22
-rw-r--r--crates/ra_ide/src/join_lines.rs11
-rw-r--r--crates/ra_ide/src/lib.rs7
-rw-r--r--crates/ra_ide/src/matching_brace.rs13
-rw-r--r--crates/ra_ide/src/mock_analysis.rs123
-rw-r--r--crates/ra_ide/src/parent_module.rs12
-rw-r--r--crates/ra_ide/src/references.rs27
-rw-r--r--crates/ra_ide/src/runnables.rs440
-rw-r--r--crates/ra_ide/src/snapshots/highlight_injection.html2
-rw-r--r--crates/ra_ide/src/snapshots/highlight_strings.html3
-rw-r--r--crates/ra_ide/src/snapshots/highlight_unsafe.html48
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html14
-rw-r--r--crates/ra_ide/src/snapshots/rainbow_highlighting.html2
-rw-r--r--crates/ra_ide/src/ssr.rs32
-rw-r--r--crates/ra_ide/src/status.rs11
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs223
-rw-r--r--crates/ra_ide/src/syntax_highlighting/html.rs2
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs16
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs32
-rw-r--r--crates/ra_ide/src/syntax_tree.rs16
-rw-r--r--crates/ra_ide/src/typing.rs7
-rw-r--r--crates/ra_ide/src/typing/on_enter.rs11
-rw-r--r--crates/ra_ide_db/src/search.rs40
-rw-r--r--crates/ra_ide_db/src/symbol_index.rs21
-rw-r--r--crates/ra_parser/src/grammar.rs7
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs16
-rw-r--r--crates/ra_proc_macro_srv/Cargo.toml1
-rw-r--r--crates/ra_proc_macro_srv/src/tests/utils.rs3
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs2
-rw-r--r--crates/ra_project_model/src/json_project.rs89
-rw-r--r--crates/ra_project_model/src/lib.rs60
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/src/ast.rs2
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs4
-rw-r--r--crates/ra_syntax/src/ast/tokens.rs10
-rw-r--r--crates/ra_syntax/src/ast/traits.rs13
-rw-r--r--crates/ra_syntax/src/syntax_node.rs4
-rw-r--r--crates/ra_syntax/src/validation.rs20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast172
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rs6
-rw-r--r--crates/rust-analyzer/Cargo.toml3
-rw-r--r--crates/rust-analyzer/src/bin/main.rs41
-rw-r--r--crates/rust-analyzer/src/caps.rs5
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs87
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs5
-rw-r--r--crates/rust-analyzer/src/config.rs56
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap2
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs3
-rw-r--r--crates/rust-analyzer/src/from_proto.rs8
-rw-r--r--crates/rust-analyzer/src/global_state.rs (renamed from crates/rust-analyzer/src/world.rs)42
-rw-r--r--crates/rust-analyzer/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs68
-rw-r--r--crates/rust-analyzer/src/main_loop.rs151
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs496
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs3
-rw-r--r--crates/rust-analyzer/src/to_proto.rs148
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs163
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs33
-rw-r--r--crates/stdx/src/lib.rs5
-rw-r--r--crates/test_utils/Cargo.toml5
-rw-r--r--crates/test_utils/src/lib.rs156
-rw-r--r--docs/dev/README.md105
-rw-r--r--docs/dev/lsp-extensions.md341
-rw-r--r--docs/dev/lsp-features.md72
-rw-r--r--docs/user/assists.md769
-rw-r--r--docs/user/features.md212
-rw-r--r--docs/user/manual.adoc (renamed from docs/user/readme.adoc)96
-rw-r--r--editors/code/.vscodeignore2
-rw-r--r--editors/code/package-lock.json1314
-rw-r--r--editors/code/package.json151
-rw-r--r--editors/code/rollup.config.js4
-rw-r--r--editors/code/rust.tmGrammar.json9
-rw-r--r--editors/code/src/ast_inspector.ts (renamed from editors/code/src/commands/syntax_tree.ts)88
-rw-r--r--editors/code/src/commands.ts416
-rw-r--r--editors/code/src/commands/analyzer_status.ts51
-rw-r--r--editors/code/src/commands/expand_macro.ts66
-rw-r--r--editors/code/src/commands/join_lines.ts22
-rw-r--r--editors/code/src/commands/matching_brace.ts27
-rw-r--r--editors/code/src/commands/on_enter.ts35
-rw-r--r--editors/code/src/commands/parent_module.ts29
-rw-r--r--editors/code/src/commands/server_version.ts15
-rw-r--r--editors/code/src/commands/ssr.ts30
-rw-r--r--editors/code/src/config.ts2
-rw-r--r--editors/code/src/debug.ts123
-rw-r--r--editors/code/src/inlay_hints.ts2
-rw-r--r--editors/code/src/lsp_ext.ts86
-rw-r--r--editors/code/src/main.ts57
-rw-r--r--editors/code/src/run.ts (renamed from editors/code/src/commands/runnables.ts)116
-rw-r--r--editors/code/src/rust-analyzer-api.ts125
-rw-r--r--editors/code/src/snippets.ts (renamed from editors/code/src/commands/index.ts)58
-rw-r--r--editors/code/src/source_change.ts54
-rw-r--r--editors/code/src/tasks.ts7
-rw-r--r--editors/code/src/toolchain.ts (renamed from editors/code/src/cargo.ts)128
-rw-r--r--editors/code/src/util.ts32
-rw-r--r--editors/code/tests/runTests.ts43
-rw-r--r--editors/code/tests/unit/index.ts38
-rw-r--r--editors/code/tests/unit/launch_config.test.ts52
-rw-r--r--editors/code/tsconfig.json9
-rw-r--r--xtask/src/ast_src.rs6
-rw-r--r--xtask/src/codegen.rs89
-rw-r--r--xtask/src/codegen/gen_assists_docs.rs210
-rw-r--r--xtask/src/codegen/gen_feature_docs.rs75
-rw-r--r--xtask/src/lib.rs8
-rw-r--r--xtask/src/main.rs2
-rw-r--r--xtask/tests/tidy.rs25
172 files changed, 6898 insertions, 3673 deletions
diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js
index 2c7eedbe2..b499cd0fd 100644
--- a/.github/actions/github-release/main.js
+++ b/.github/actions/github-release/main.js
@@ -16,7 +16,7 @@ async function runOnce() {
16 const slug = process.env.GITHUB_REPOSITORY; 16 const slug = process.env.GITHUB_REPOSITORY;
17 const owner = slug.split('/')[0]; 17 const owner = slug.split('/')[0];
18 const repo = slug.split('/')[1]; 18 const repo = slug.split('/')[1];
19 const sha = process.env.GITHUB_SHA; 19 const sha = process.env.HEAD_SHA;
20 20
21 core.info(`files: ${files}`); 21 core.info(`files: ${files}`);
22 core.info(`name: ${name}`); 22 core.info(`name: ${name}`);
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 00f299ff1..ed9191c49 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -97,7 +97,13 @@ jobs:
97 97
98 typescript: 98 typescript:
99 name: TypeScript 99 name: TypeScript
100 runs-on: ubuntu-latest 100 strategy:
101 fail-fast: false
102 matrix:
103 os: [ubuntu-latest, windows-latest, macos-latest]
104
105 runs-on: ${{ matrix.os }}
106
101 steps: 107 steps:
102 - name: Checkout repository 108 - name: Checkout repository
103 uses: actions/checkout@v2 109 uses: actions/checkout@v2
@@ -111,10 +117,19 @@ jobs:
111 working-directory: ./editors/code 117 working-directory: ./editors/code
112 118
113 - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; } 119 - run: npm audit || { sleep 10 && npm audit; } || { sleep 30 && npm audit; }
120 if: runner.os == 'Linux'
114 working-directory: ./editors/code 121 working-directory: ./editors/code
115 122
116 - run: npm run lint 123 - run: npm run lint
117 working-directory: ./editors/code 124 working-directory: ./editors/code
118 125
126 - name: Run vscode tests
127 uses: GabrielBB/[email protected]
128 env:
129 VSCODE_CLI: 1
130 with:
131 run: npm --prefix ./editors/code test
132 # working-directory: ./editors/code # does not work: https://github.com/GabrielBB/xvfb-action/issues/8
133
119 - run: npm run package --scripts-prepend-node-path 134 - run: npm run package --scripts-prepend-node-path
120 working-directory: ./editors/code 135 working-directory: ./editors/code
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 29ac89549..1ae8ed1b6 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -6,7 +6,7 @@ on:
6 push: 6 push:
7 branches: 7 branches:
8 - release 8 - release
9 - nightly 9 - trigger-nightly
10 10
11env: 11env:
12 CARGO_INCREMENTAL: 0 12 CARGO_INCREMENTAL: 0
@@ -88,6 +88,9 @@ jobs:
88 - name: Checkout repository 88 - name: Checkout repository
89 uses: actions/checkout@v2 89 uses: actions/checkout@v2
90 90
91 - run: echo "::set-env name=HEAD_SHA::$(git rev-parse HEAD)"
92 - run: 'echo "HEAD_SHA: $HEAD_SHA"'
93
91 - uses: actions/download-artifact@v1 94 - uses: actions/download-artifact@v1
92 with: 95 with:
93 name: dist-macos-latest 96 name: dist-macos-latest
diff --git a/.gitignore b/.gitignore
index f835edef0..aef0fac33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,6 @@ crates/*/target
7*.log 7*.log
8*.iml 8*.iml
9.vscode/settings.json 9.vscode/settings.json
10cargo-timing*.html 10*.html
11generated_assists.adoc
12generated_features.adoc
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6a2fff906..8ca27d878 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -71,6 +71,28 @@
71 } 71 }
72 }, 72 },
73 { 73 {
74 // Used for testing the extension with a local build of the LSP server (in `target/release`)
75 // with all other extendions loaded.
76 "name": "Run With Extensions",
77 "type": "extensionHost",
78 "request": "launch",
79 "runtimeExecutable": "${execPath}",
80 "args": [
81 "--disable-extension", "matklad.rust-analyzer",
82 "--extensionDevelopmentPath=${workspaceFolder}/editors/code"
83 ],
84 "outFiles": [
85 "${workspaceFolder}/editors/code/out/**/*.js"
86 ],
87 "preLaunchTask": "Build Server (Release) and Extension",
88 "skipFiles": [
89 "<node_internals>/**/*.js"
90 ],
91 "env": {
92 "__RA_LSP_SERVER_DEBUG": "${workspaceFolder}/target/release/rust-analyzer"
93 }
94 },
95 {
74 // Used to attach LLDB to a running LSP server. 96 // Used to attach LLDB to a running LSP server.
75 // NOTE: Might require root permissions. For this run: 97 // NOTE: Might require root permissions. For this run:
76 // 98 //
@@ -87,5 +109,17 @@
87 "rust" 109 "rust"
88 ] 110 ]
89 }, 111 },
112 {
113 "name": "Run Unit Tests",
114 "type": "extensionHost",
115 "request": "launch",
116 "runtimeExecutable": "${execPath}",
117 "args": [
118 "--extensionDevelopmentPath=${workspaceFolder}/editors/code",
119 "--extensionTestsPath=${workspaceFolder}/editors/code/out/tests/unit" ],
120 "sourceMaps": true,
121 "outFiles": [ "${workspaceFolder}/editors/code/out/tests/unit/**/*.js" ],
122 "preLaunchTask": "Pretest"
123 }
90 ] 124 ]
91} 125}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 0969ce89a..a25dff19e 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -40,6 +40,18 @@
40 "command": "cargo build --release --package rust-analyzer", 40 "command": "cargo build --release --package rust-analyzer",
41 "problemMatcher": "$rustc" 41 "problemMatcher": "$rustc"
42 }, 42 },
43 {
44 "label": "Pretest",
45 "group": "build",
46 "isBackground": false,
47 "type": "npm",
48 "script": "pretest",
49 "path": "editors/code/",
50 "problemMatcher": {
51 "base": "$tsc",
52 "fileLocation": ["relative", "${workspaceFolder}/editors/code/"]
53 }
54 },
43 55
44 { 56 {
45 "label": "Build Server and Extension", 57 "label": "Build Server and Extension",
diff --git a/Cargo.lock b/Cargo.lock
index 007f05b4d..5f88ad0c4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -101,9 +101,9 @@ dependencies = [
101 101
102[[package]] 102[[package]]
103name = "cc" 103name = "cc"
104version = "1.0.53" 104version = "1.0.54"
105source = "registry+https://github.com/rust-lang/crates.io-index" 105source = "registry+https://github.com/rust-lang/crates.io-index"
106checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" 106checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
107 107
108[[package]] 108[[package]]
109name = "cfg-if" 109name = "cfg-if"
@@ -114,7 +114,7 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
114[[package]] 114[[package]]
115name = "chalk-derive" 115name = "chalk-derive"
116version = "0.10.1-dev" 116version = "0.10.1-dev"
117source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" 117source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c"
118dependencies = [ 118dependencies = [
119 "proc-macro2", 119 "proc-macro2",
120 "quote", 120 "quote",
@@ -125,51 +125,30 @@ dependencies = [
125[[package]] 125[[package]]
126name = "chalk-engine" 126name = "chalk-engine"
127version = "0.10.1-dev" 127version = "0.10.1-dev"
128source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" 128source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c"
129dependencies = [ 129dependencies = [
130 "chalk-macros", 130 "chalk-derive",
131 "chalk-ir",
131 "rustc-hash", 132 "rustc-hash",
132] 133]
133 134
134[[package]] 135[[package]]
135name = "chalk-ir" 136name = "chalk-ir"
136version = "0.10.1-dev" 137version = "0.10.1-dev"
137source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" 138source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c"
138dependencies = [ 139dependencies = [
139 "chalk-derive", 140 "chalk-derive",
140 "chalk-engine",
141 "chalk-macros",
142]
143
144[[package]]
145name = "chalk-macros"
146version = "0.10.1-dev"
147source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96"
148dependencies = [
149 "lazy_static", 141 "lazy_static",
150] 142]
151 143
152[[package]] 144[[package]]
153name = "chalk-rust-ir"
154version = "0.10.1-dev"
155source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96"
156dependencies = [
157 "chalk-derive",
158 "chalk-engine",
159 "chalk-ir",
160 "chalk-macros",
161]
162
163[[package]]
164name = "chalk-solve" 145name = "chalk-solve"
165version = "0.10.1-dev" 146version = "0.10.1-dev"
166source = "git+https://github.com/rust-lang/chalk.git?rev=eaab84b394007d1bed15f5470409a6ea02900a96#eaab84b394007d1bed15f5470409a6ea02900a96" 147source = "git+https://github.com/rust-lang/chalk.git?rev=329b7f3fdd2431ed6f6778cde53f22374c7d094c#329b7f3fdd2431ed6f6778cde53f22374c7d094c"
167dependencies = [ 148dependencies = [
168 "chalk-derive", 149 "chalk-derive",
169 "chalk-engine", 150 "chalk-engine",
170 "chalk-ir", 151 "chalk-ir",
171 "chalk-macros",
172 "chalk-rust-ir",
173 "ena", 152 "ena",
174 "itertools", 153 "itertools",
175 "petgraph", 154 "petgraph",
@@ -264,9 +243,9 @@ dependencies = [
264 243
265[[package]] 244[[package]]
266name = "crossbeam-queue" 245name = "crossbeam-queue"
267version = "0.2.1" 246version = "0.2.2"
268source = "registry+https://github.com/rust-lang/crates.io-index" 247source = "registry+https://github.com/rust-lang/crates.io-index"
269checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" 248checksum = "ab6bffe714b6bb07e42f201352c34f51fefd355ace793f9e638ebd52d23f98d2"
270dependencies = [ 249dependencies = [
271 "cfg-if", 250 "cfg-if",
272 "crossbeam-utils", 251 "crossbeam-utils",
@@ -382,9 +361,9 @@ dependencies = [
382 361
383[[package]] 362[[package]]
384name = "fst" 363name = "fst"
385version = "0.4.3" 364version = "0.4.4"
386source = "registry+https://github.com/rust-lang/crates.io-index" 365source = "registry+https://github.com/rust-lang/crates.io-index"
387checksum = "81f9cac32c1741cdf6b66be7dcf0d9c7f25ccf12f8aa84c16cfa31f9f14513b3" 366checksum = "a7293de202dbfe786c0b3fe6110a027836c5438ed06db7b715c9955ff4bfea51"
388 367
389[[package]] 368[[package]]
390name = "fuchsia-zircon" 369name = "fuchsia-zircon"
@@ -483,9 +462,9 @@ dependencies = [
483 462
484[[package]] 463[[package]]
485name = "indexmap" 464name = "indexmap"
486version = "1.3.2" 465version = "1.4.0"
487source = "registry+https://github.com/rust-lang/crates.io-index" 466source = "registry+https://github.com/rust-lang/crates.io-index"
488checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" 467checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
489dependencies = [ 468dependencies = [
490 "autocfg", 469 "autocfg",
491] 470]
@@ -610,9 +589,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
610 589
611[[package]] 590[[package]]
612name = "libc" 591name = "libc"
613version = "0.2.70" 592version = "0.2.71"
614source = "registry+https://github.com/rust-lang/crates.io-index" 593source = "registry+https://github.com/rust-lang/crates.io-index"
615checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" 594checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
616 595
617[[package]] 596[[package]]
618name = "libloading" 597name = "libloading"
@@ -661,9 +640,9 @@ dependencies = [
661 640
662[[package]] 641[[package]]
663name = "lsp-types" 642name = "lsp-types"
664version = "0.74.1" 643version = "0.74.2"
665source = "registry+https://github.com/rust-lang/crates.io-index" 644source = "registry+https://github.com/rust-lang/crates.io-index"
666checksum = "57c0e6a2b8837d27b29deb3f3e6dc1c6d2f57947677f9be1024e482ec5b59525" 645checksum = "b360754e89e0e13c114245131382ba921d4ff1efabb918e549422938aaa8d392"
667dependencies = [ 646dependencies = [
668 "base64", 647 "base64",
669 "bitflags", 648 "bitflags",
@@ -830,9 +809,9 @@ dependencies = [
830 809
831[[package]] 810[[package]]
832name = "paste" 811name = "paste"
833version = "0.1.12" 812version = "0.1.16"
834source = "registry+https://github.com/rust-lang/crates.io-index" 813source = "registry+https://github.com/rust-lang/crates.io-index"
835checksum = "0a229b1c58c692edcaa5b9b0948084f130f55d2dcc15b02fcc5340b2b4521476" 814checksum = "d508492eeb1e5c38ee696371bf7b9fc33c83d46a7d451606b96458fbbbdc2dec"
836dependencies = [ 815dependencies = [
837 "paste-impl", 816 "paste-impl",
838 "proc-macro-hack", 817 "proc-macro-hack",
@@ -840,9 +819,9 @@ dependencies = [
840 819
841[[package]] 820[[package]]
842name = "paste-impl" 821name = "paste-impl"
843version = "0.1.12" 822version = "0.1.16"
844source = "registry+https://github.com/rust-lang/crates.io-index" 823source = "registry+https://github.com/rust-lang/crates.io-index"
845checksum = "2e0bf239e447e67ff6d16a8bb5e4d4bd2343acf5066061c0e8e06ac5ba8ca68c" 824checksum = "84f328a6a63192b333fce5fbb4be79db6758a4d518dfac6d54412f1492f72d32"
846dependencies = [ 825dependencies = [
847 "proc-macro-hack", 826 "proc-macro-hack",
848 "proc-macro2", 827 "proc-macro2",
@@ -858,9 +837,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
858 837
859[[package]] 838[[package]]
860name = "petgraph" 839name = "petgraph"
861version = "0.5.0" 840version = "0.5.1"
862source = "registry+https://github.com/rust-lang/crates.io-index" 841source = "registry+https://github.com/rust-lang/crates.io-index"
863checksum = "29c127eea4a29ec6c85d153c59dc1213f33ec74cead30fe4730aecc88cc1fd92" 842checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
864dependencies = [ 843dependencies = [
865 "fixedbitset", 844 "fixedbitset",
866 "indexmap", 845 "indexmap",
@@ -886,15 +865,15 @@ checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
886 865
887[[package]] 866[[package]]
888name = "proc-macro-hack" 867name = "proc-macro-hack"
889version = "0.5.15" 868version = "0.5.16"
890source = "registry+https://github.com/rust-lang/crates.io-index" 869source = "registry+https://github.com/rust-lang/crates.io-index"
891checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" 870checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4"
892 871
893[[package]] 872[[package]]
894name = "proc-macro2" 873name = "proc-macro2"
895version = "1.0.13" 874version = "1.0.18"
896source = "registry+https://github.com/rust-lang/crates.io-index" 875source = "registry+https://github.com/rust-lang/crates.io-index"
897checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639" 876checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
898dependencies = [ 877dependencies = [
899 "unicode-xid", 878 "unicode-xid",
900] 879]
@@ -1036,7 +1015,6 @@ version = "0.1.0"
1036dependencies = [ 1015dependencies = [
1037 "arrayvec", 1016 "arrayvec",
1038 "chalk-ir", 1017 "chalk-ir",
1039 "chalk-rust-ir",
1040 "chalk-solve", 1018 "chalk-solve",
1041 "ena", 1019 "ena",
1042 "insta", 1020 "insta",
@@ -1141,6 +1119,7 @@ dependencies = [
1141 "memmap", 1119 "memmap",
1142 "ra_mbe", 1120 "ra_mbe",
1143 "ra_proc_macro", 1121 "ra_proc_macro",
1122 "ra_toolchain",
1144 "ra_tt", 1123 "ra_tt",
1145 "serde_derive", 1124 "serde_derive",
1146 "test_utils", 1125 "test_utils",
@@ -1313,9 +1292,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
1313 1292
1314[[package]] 1293[[package]]
1315name = "regex" 1294name = "regex"
1316version = "1.3.7" 1295version = "1.3.9"
1317source = "registry+https://github.com/rust-lang/crates.io-index" 1296source = "registry+https://github.com/rust-lang/crates.io-index"
1318checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" 1297checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
1319dependencies = [ 1298dependencies = [
1320 "aho-corasick", 1299 "aho-corasick",
1321 "memchr", 1300 "memchr",
@@ -1325,9 +1304,9 @@ dependencies = [
1325 1304
1326[[package]] 1305[[package]]
1327name = "regex-syntax" 1306name = "regex-syntax"
1328version = "0.6.17" 1307version = "0.6.18"
1329source = "registry+https://github.com/rust-lang/crates.io-index" 1308source = "registry+https://github.com/rust-lang/crates.io-index"
1330checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" 1309checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
1331 1310
1332[[package]] 1311[[package]]
1333name = "relative-path" 1312name = "relative-path"
@@ -1372,17 +1351,20 @@ dependencies = [
1372 "lsp-types", 1351 "lsp-types",
1373 "parking_lot", 1352 "parking_lot",
1374 "pico-args", 1353 "pico-args",
1354 "ra_cfg",
1375 "ra_db", 1355 "ra_db",
1376 "ra_flycheck", 1356 "ra_flycheck",
1377 "ra_hir", 1357 "ra_hir",
1378 "ra_hir_def", 1358 "ra_hir_def",
1379 "ra_hir_ty", 1359 "ra_hir_ty",
1380 "ra_ide", 1360 "ra_ide",
1361 "ra_mbe",
1381 "ra_proc_macro_srv", 1362 "ra_proc_macro_srv",
1382 "ra_prof", 1363 "ra_prof",
1383 "ra_project_model", 1364 "ra_project_model",
1384 "ra_syntax", 1365 "ra_syntax",
1385 "ra_text_edit", 1366 "ra_text_edit",
1367 "ra_tt",
1386 "ra_vfs", 1368 "ra_vfs",
1387 "rand", 1369 "rand",
1388 "relative-path", 1370 "relative-path",
@@ -1398,9 +1380,9 @@ dependencies = [
1398 1380
1399[[package]] 1381[[package]]
1400name = "rustc-ap-rustc_lexer" 1382name = "rustc-ap-rustc_lexer"
1401version = "656.0.0" 1383version = "661.0.0"
1402source = "registry+https://github.com/rust-lang/crates.io-index" 1384source = "registry+https://github.com/rust-lang/crates.io-index"
1403checksum = "9cbba98ec46e96a4663197dfa8c0378752de2006e314e5400c0ca74929d6692f" 1385checksum = "a6d88abd7c634b52557e46fc7ba47644f0cbe45c358c33f51c532d60d1da239e"
1404dependencies = [ 1386dependencies = [
1405 "unicode-xid", 1387 "unicode-xid",
1406] 1388]
@@ -1419,9 +1401,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
1419 1401
1420[[package]] 1402[[package]]
1421name = "ryu" 1403name = "ryu"
1422version = "1.0.4" 1404version = "1.0.5"
1423source = "registry+https://github.com/rust-lang/crates.io-index" 1405source = "registry+https://github.com/rust-lang/crates.io-index"
1424checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" 1406checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
1425 1407
1426[[package]] 1408[[package]]
1427name = "salsa" 1409name = "salsa"
@@ -1510,18 +1492,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1510 1492
1511[[package]] 1493[[package]]
1512name = "serde" 1494name = "serde"
1513version = "1.0.110" 1495version = "1.0.111"
1514source = "registry+https://github.com/rust-lang/crates.io-index" 1496source = "registry+https://github.com/rust-lang/crates.io-index"
1515checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" 1497checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
1516dependencies = [ 1498dependencies = [
1517 "serde_derive", 1499 "serde_derive",
1518] 1500]
1519 1501
1520[[package]] 1502[[package]]
1521name = "serde_derive" 1503name = "serde_derive"
1522version = "1.0.110" 1504version = "1.0.111"
1523source = "registry+https://github.com/rust-lang/crates.io-index" 1505source = "registry+https://github.com/rust-lang/crates.io-index"
1524checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" 1506checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
1525dependencies = [ 1507dependencies = [
1526 "proc-macro2", 1508 "proc-macro2",
1527 "quote", 1509 "quote",
@@ -1595,9 +1577,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
1595 1577
1596[[package]] 1578[[package]]
1597name = "syn" 1579name = "syn"
1598version = "1.0.22" 1580version = "1.0.30"
1599source = "registry+https://github.com/rust-lang/crates.io-index" 1581source = "registry+https://github.com/rust-lang/crates.io-index"
1600checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac" 1582checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
1601dependencies = [ 1583dependencies = [
1602 "proc-macro2", 1584 "proc-macro2",
1603 "quote", 1585 "quote",
@@ -1654,7 +1636,11 @@ name = "test_utils"
1654version = "0.1.0" 1636version = "0.1.0"
1655dependencies = [ 1637dependencies = [
1656 "difference", 1638 "difference",
1639 "ra_cfg",
1640 "relative-path",
1641 "rustc-hash",
1657 "serde_json", 1642 "serde_json",
1643 "stdx",
1658 "text-size", 1644 "text-size",
1659] 1645]
1660 1646
@@ -1813,9 +1799,9 @@ dependencies = [
1813 1799
1814[[package]] 1800[[package]]
1815name = "yaml-rust" 1801name = "yaml-rust"
1816version = "0.4.3" 1802version = "0.4.4"
1817source = "registry+https://github.com/rust-lang/crates.io-index" 1803source = "registry+https://github.com/rust-lang/crates.io-index"
1818checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" 1804checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
1819dependencies = [ 1805dependencies = [
1820 "linked-hash-map", 1806 "linked-hash-map",
1821] 1807]
diff --git a/Cargo.toml b/Cargo.toml
index c034e2424..5278b5a16 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,8 +22,6 @@ opt-level = 0
22opt-level = 0 22opt-level = 0
23[profile.release.package.chalk-derive] 23[profile.release.package.chalk-derive]
24opt-level = 0 24opt-level = 0
25[profile.release.package.chalk-macros]
26opt-level = 0
27[profile.release.package.salsa-macros] 25[profile.release.package.salsa-macros]
28opt-level = 0 26opt-level = 0
29[profile.release.package.xtask] 27[profile.release.package.xtask]
diff --git a/README.md b/README.md
index 1c334d55e..1e7c3e9b4 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,13 @@ If you want to **use** rust-analyzer's language server with your editor of
27choice, check [the manual](https://rust-analyzer.github.io/manual.html) folder. It also contains some tips & tricks to help 27choice, check [the manual](https://rust-analyzer.github.io/manual.html) folder. It also contains some tips & tricks to help
28you be more productive when using rust-analyzer. 28you be more productive when using rust-analyzer.
29 29
30## Getting in touch 30## Communication
31 31
32We are on the rust-lang Zulip! 32For usage and troubleshooting requests, please use "IDEs and Editors" category of the Rust forum:
33
34https://users.rust-lang.org/c/ide/14
35
36For questions about development and implementation, join rls-2.0 working group on Zulip:
33 37
34https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 38https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0
35 39
diff --git a/bors.toml b/bors.toml
index 0bc71860f..13ce236df 100644
--- a/bors.toml
+++ b/bors.toml
@@ -2,6 +2,8 @@ status = [
2 "Rust (ubuntu-latest)", 2 "Rust (ubuntu-latest)",
3 "Rust (windows-latest)", 3 "Rust (windows-latest)",
4 "Rust (macos-latest)", 4 "Rust (macos-latest)",
5 "TypeScript" 5 "TypeScript (ubuntu-latest)",
6 "TypeScript (windows-latest)",
7 "TypeScript (macos-latest)",
6] 8]
7delete_merged_branches = true 9delete_merged_branches = true
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
index 6a675e812..776bddf91 100644
--- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
+++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
@@ -4,9 +4,9 @@ use test_utils::mark;
4 4
5use crate::{utils::FamousDefs, AssistContext, AssistId, Assists}; 5use crate::{utils::FamousDefs, AssistContext, AssistId, Assists};
6 6
7// Assist add_from_impl_for_enum 7// Assist: add_from_impl_for_enum
8// 8//
9// Adds a From impl for an enum variant with one tuple field 9// Adds a From impl for an enum variant with one tuple field.
10// 10//
11// ``` 11// ```
12// enum A { <|>One(u32) } 12// enum A { <|>One(u32) }
diff --git a/crates/ra_assists/src/handlers/introduce_named_lifetime.rs b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs
new file mode 100644
index 000000000..beb5b7366
--- /dev/null
+++ b/crates/ra_assists/src/handlers/introduce_named_lifetime.rs
@@ -0,0 +1,303 @@
1use ra_syntax::{
2 ast::{self, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
3 AstNode, SyntaxKind, TextRange, TextSize,
4};
5use rustc_hash::FxHashSet;
6
7use crate::{assist_context::AssistBuilder, AssistContext, AssistId, Assists};
8
9static ASSIST_NAME: &str = "introduce_named_lifetime";
10static ASSIST_LABEL: &str = "Introduce named lifetime";
11
12// Assist: introduce_named_lifetime
13//
14// Change an anonymous lifetime to a named lifetime.
15//
16// ```
17// impl Cursor<'_<|>> {
18// fn node(self) -> &SyntaxNode {
19// match self {
20// Cursor::Replace(node) | Cursor::Before(node) => node,
21// }
22// }
23// }
24// ```
25// ->
26// ```
27// impl<'a> Cursor<'a> {
28// fn node(self) -> &SyntaxNode {
29// match self {
30// Cursor::Replace(node) | Cursor::Before(node) => node,
31// }
32// }
33// }
34// ```
35// FIXME: How can we handle renaming any one of multiple anonymous lifetimes?
36// FIXME: should also add support for the case fun(f: &Foo) -> &<|>Foo
37pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
38 let lifetime_token = ctx
39 .find_token_at_offset(SyntaxKind::LIFETIME)
40 .filter(|lifetime| lifetime.text() == "'_")?;
41 if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::FnDef::cast) {
42 generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range())
43 } else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::ImplDef::cast) {
44 // only allow naming the last anonymous lifetime
45 lifetime_token.next_token().filter(|tok| tok.kind() == SyntaxKind::R_ANGLE)?;
46 generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range())
47 } else {
48 None
49 }
50}
51
52/// Generate the assist for the fn def case
53fn generate_fn_def_assist(
54 acc: &mut Assists,
55 fn_def: &ast::FnDef,
56 lifetime_loc: TextRange,
57) -> Option<()> {
58 let param_list: ast::ParamList = fn_def.param_list()?;
59 let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.type_param_list())?;
60 let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end();
61 let self_param =
62 // use the self if it's a reference and has no explicit lifetime
63 param_list.self_param().filter(|p| p.lifetime_token().is_none() && p.amp_token().is_some());
64 // compute the location which implicitly has the same lifetime as the anonymous lifetime
65 let loc_needing_lifetime = if let Some(self_param) = self_param {
66 // if we have a self reference, use that
67 Some(self_param.self_token()?.text_range().start())
68 } else {
69 // otherwise, if there's a single reference parameter without a named liftime, use that
70 let fn_params_without_lifetime: Vec<_> = param_list
71 .params()
72 .filter_map(|param| match param.ascribed_type() {
73 Some(ast::TypeRef::ReferenceType(ascribed_type))
74 if ascribed_type.lifetime_token() == None =>
75 {
76 Some(ascribed_type.amp_token()?.text_range().end())
77 }
78 _ => None,
79 })
80 .collect();
81 match fn_params_without_lifetime.len() {
82 1 => Some(fn_params_without_lifetime.into_iter().nth(0)?),
83 0 => None,
84 // multiple unnnamed is invalid. assist is not applicable
85 _ => return None,
86 }
87 };
88 acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| {
89 add_lifetime_param(fn_def, builder, end_of_fn_ident, new_lifetime_param);
90 builder.replace(lifetime_loc, format!("'{}", new_lifetime_param));
91 loc_needing_lifetime.map(|loc| builder.insert(loc, format!("'{} ", new_lifetime_param)));
92 })
93}
94
95/// Generate the assist for the impl def case
96fn generate_impl_def_assist(
97 acc: &mut Assists,
98 impl_def: &ast::ImplDef,
99 lifetime_loc: TextRange,
100) -> Option<()> {
101 let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?;
102 let end_of_impl_kw = impl_def.impl_token()?.text_range().end();
103 acc.add(AssistId(ASSIST_NAME), ASSIST_LABEL, lifetime_loc, |builder| {
104 add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param);
105 builder.replace(lifetime_loc, format!("'{}", new_lifetime_param));
106 })
107}
108
109/// Given a type parameter list, generate a unique lifetime parameter name
110/// which is not in the list
111fn generate_unique_lifetime_param_name(
112 existing_type_param_list: &Option<ast::TypeParamList>,
113) -> Option<char> {
114 match existing_type_param_list {
115 Some(type_params) => {
116 let used_lifetime_params: FxHashSet<_> = type_params
117 .lifetime_params()
118 .map(|p| p.syntax().text().to_string()[1..].to_owned())
119 .collect();
120 (b'a'..=b'z').map(char::from).find(|c| !used_lifetime_params.contains(&c.to_string()))
121 }
122 None => Some('a'),
123 }
124}
125
126/// Add the lifetime param to `builder`. If there are type parameters in `type_params_owner`, add it to the end. Otherwise
127/// add new type params brackets with the lifetime parameter at `new_type_params_loc`.
128fn add_lifetime_param<TypeParamsOwner: ast::TypeParamsOwner>(
129 type_params_owner: &TypeParamsOwner,
130 builder: &mut AssistBuilder,
131 new_type_params_loc: TextSize,
132 new_lifetime_param: char,
133) {
134 match type_params_owner.type_param_list() {
135 // add the new lifetime parameter to an existing type param list
136 Some(type_params) => {
137 builder.insert(
138 (u32::from(type_params.syntax().text_range().end()) - 1).into(),
139 format!(", '{}", new_lifetime_param),
140 );
141 }
142 // create a new type param list containing only the new lifetime parameter
143 None => {
144 builder.insert(new_type_params_loc, format!("<'{}>", new_lifetime_param));
145 }
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use crate::tests::{check_assist, check_assist_not_applicable};
153
154 #[test]
155 fn test_example_case() {
156 check_assist(
157 introduce_named_lifetime,
158 r#"impl Cursor<'_<|>> {
159 fn node(self) -> &SyntaxNode {
160 match self {
161 Cursor::Replace(node) | Cursor::Before(node) => node,
162 }
163 }
164 }"#,
165 r#"impl<'a> Cursor<'a> {
166 fn node(self) -> &SyntaxNode {
167 match self {
168 Cursor::Replace(node) | Cursor::Before(node) => node,
169 }
170 }
171 }"#,
172 );
173 }
174
175 #[test]
176 fn test_example_case_simplified() {
177 check_assist(
178 introduce_named_lifetime,
179 r#"impl Cursor<'_<|>> {"#,
180 r#"impl<'a> Cursor<'a> {"#,
181 );
182 }
183
184 #[test]
185 fn test_example_case_cursor_after_tick() {
186 check_assist(
187 introduce_named_lifetime,
188 r#"impl Cursor<'<|>_> {"#,
189 r#"impl<'a> Cursor<'a> {"#,
190 );
191 }
192
193 #[test]
194 fn test_example_case_cursor_before_tick() {
195 check_assist(
196 introduce_named_lifetime,
197 r#"impl Cursor<<|>'_> {"#,
198 r#"impl<'a> Cursor<'a> {"#,
199 );
200 }
201
202 #[test]
203 fn test_not_applicable_cursor_position() {
204 check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'_><|> {"#);
205 check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<|><'_> {"#);
206 }
207
208 #[test]
209 fn test_not_applicable_lifetime_already_name() {
210 check_assist_not_applicable(introduce_named_lifetime, r#"impl Cursor<'a<|>> {"#);
211 check_assist_not_applicable(introduce_named_lifetime, r#"fn my_fun<'a>() -> X<'a<|>>"#);
212 }
213
214 #[test]
215 fn test_with_type_parameter() {
216 check_assist(
217 introduce_named_lifetime,
218 r#"impl<T> Cursor<T, '_<|>>"#,
219 r#"impl<T, 'a> Cursor<T, 'a>"#,
220 );
221 }
222
223 #[test]
224 fn test_with_existing_lifetime_name_conflict() {
225 check_assist(
226 introduce_named_lifetime,
227 r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#,
228 r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#,
229 );
230 }
231
232 #[test]
233 fn test_function_return_value_anon_lifetime_param() {
234 check_assist(
235 introduce_named_lifetime,
236 r#"fn my_fun() -> X<'_<|>>"#,
237 r#"fn my_fun<'a>() -> X<'a>"#,
238 );
239 }
240
241 #[test]
242 fn test_function_return_value_anon_reference_lifetime() {
243 check_assist(
244 introduce_named_lifetime,
245 r#"fn my_fun() -> &'_<|> X"#,
246 r#"fn my_fun<'a>() -> &'a X"#,
247 );
248 }
249
250 #[test]
251 fn test_function_param_anon_lifetime() {
252 check_assist(
253 introduce_named_lifetime,
254 r#"fn my_fun(x: X<'_<|>>)"#,
255 r#"fn my_fun<'a>(x: X<'a>)"#,
256 );
257 }
258
259 #[test]
260 fn test_function_add_lifetime_to_params() {
261 check_assist(
262 introduce_named_lifetime,
263 r#"fn my_fun(f: &Foo) -> X<'_<|>>"#,
264 r#"fn my_fun<'a>(f: &'a Foo) -> X<'a>"#,
265 );
266 }
267
268 #[test]
269 fn test_function_add_lifetime_to_params_in_presence_of_other_lifetime() {
270 check_assist(
271 introduce_named_lifetime,
272 r#"fn my_fun<'other>(f: &Foo, b: &'other Bar) -> X<'_<|>>"#,
273 r#"fn my_fun<'other, 'a>(f: &'a Foo, b: &'other Bar) -> X<'a>"#,
274 );
275 }
276
277 #[test]
278 fn test_function_not_applicable_without_self_and_multiple_unnamed_param_lifetimes() {
279 // this is not permitted under lifetime elision rules
280 check_assist_not_applicable(
281 introduce_named_lifetime,
282 r#"fn my_fun(f: &Foo, b: &Bar) -> X<'_<|>>"#,
283 );
284 }
285
286 #[test]
287 fn test_function_add_lifetime_to_self_ref_param() {
288 check_assist(
289 introduce_named_lifetime,
290 r#"fn my_fun<'other>(&self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#,
291 r#"fn my_fun<'other, 'a>(&'a self, f: &Foo, b: &'other Bar) -> X<'a>"#,
292 );
293 }
294
295 #[test]
296 fn test_function_add_lifetime_to_param_with_non_ref_self() {
297 check_assist(
298 introduce_named_lifetime,
299 r#"fn my_fun<'other>(self, f: &Foo, b: &'other Bar) -> X<'_<|>>"#,
300 r#"fn my_fun<'other, 'a>(self, f: &'a Foo, b: &'other Bar) -> X<'a>"#,
301 );
302 }
303}
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs
index 30229edc2..897da2832 100644
--- a/crates/ra_assists/src/handlers/reorder_fields.rs
+++ b/crates/ra_assists/src/handlers/reorder_fields.rs
@@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, Assists};
23// ``` 23// ```
24// 24//
25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 reorder::<ast::RecordLit>(acc, ctx.clone()).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) 26 reorder::<ast::RecordLit>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx))
27} 27}
28 28
29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 9933f7a50..88ce9b62e 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -122,6 +122,7 @@ mod handlers {
122 mod flip_comma; 122 mod flip_comma;
123 mod flip_trait_bound; 123 mod flip_trait_bound;
124 mod inline_local_variable; 124 mod inline_local_variable;
125 mod introduce_named_lifetime;
125 mod introduce_variable; 126 mod introduce_variable;
126 mod invert_if; 127 mod invert_if;
127 mod merge_imports; 128 mod merge_imports;
@@ -162,6 +163,7 @@ mod handlers {
162 flip_comma::flip_comma, 163 flip_comma::flip_comma,
163 flip_trait_bound::flip_trait_bound, 164 flip_trait_bound::flip_trait_bound,
164 inline_local_variable::inline_local_variable, 165 inline_local_variable::inline_local_variable,
166 introduce_named_lifetime::introduce_named_lifetime,
165 introduce_variable::introduce_variable, 167 introduce_variable::introduce_variable,
166 invert_if::invert_if, 168 invert_if::invert_if,
167 merge_imports::merge_imports, 169 merge_imports::merge_imports,
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs
index 250e56a69..d17504529 100644
--- a/crates/ra_assists/src/tests/generated.rs
+++ b/crates/ra_assists/src/tests/generated.rs
@@ -59,6 +59,25 @@ fn main() {
59} 59}
60 60
61#[test] 61#[test]
62fn doctest_add_from_impl_for_enum() {
63 check_doc_test(
64 "add_from_impl_for_enum",
65 r#####"
66enum A { <|>One(u32) }
67"#####,
68 r#####"
69enum A { One(u32) }
70
71impl From<u32> for A {
72 fn from(v: u32) -> Self {
73 A::One(v)
74 }
75}
76"#####,
77 )
78}
79
80#[test]
62fn doctest_add_function() { 81fn doctest_add_function() {
63 check_doc_test( 82 check_doc_test(
64 "add_function", 83 "add_function",
@@ -433,6 +452,31 @@ fn main() {
433} 452}
434 453
435#[test] 454#[test]
455fn doctest_introduce_named_lifetime() {
456 check_doc_test(
457 "introduce_named_lifetime",
458 r#####"
459impl Cursor<'_<|>> {
460 fn node(self) -> &SyntaxNode {
461 match self {
462 Cursor::Replace(node) | Cursor::Before(node) => node,
463 }
464 }
465}
466"#####,
467 r#####"
468impl<'a> Cursor<'a> {
469 fn node(self) -> &SyntaxNode {
470 match self {
471 Cursor::Replace(node) | Cursor::Before(node) => node,
472 }
473 }
474}
475"#####,
476 )
477}
478
479#[test]
436fn doctest_introduce_variable() { 480fn doctest_introduce_variable() {
437 check_doc_test( 481 check_doc_test(
438 "introduce_variable", 482 "introduce_variable",
diff --git a/crates/ra_cfg/src/cfg_expr.rs b/crates/ra_cfg/src/cfg_expr.rs
index 39d71851c..85b100c6a 100644
--- a/crates/ra_cfg/src/cfg_expr.rs
+++ b/crates/ra_cfg/src/cfg_expr.rs
@@ -88,13 +88,17 @@ fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
88mod tests { 88mod tests {
89 use super::*; 89 use super::*;
90 90
91 use mbe::ast_to_token_tree; 91 use mbe::{ast_to_token_tree, TokenMap};
92 use ra_syntax::ast::{self, AstNode}; 92 use ra_syntax::ast::{self, AstNode};
93 93
94 fn assert_parse_result(input: &str, expected: CfgExpr) { 94 fn get_token_tree_generated(input: &str) -> (tt::Subtree, TokenMap) {
95 let source_file = ast::SourceFile::parse(input).ok().unwrap(); 95 let source_file = ast::SourceFile::parse(input).ok().unwrap();
96 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); 96 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
97 let (tt, _) = ast_to_token_tree(&tt).unwrap(); 97 ast_to_token_tree(&tt).unwrap()
98 }
99
100 fn assert_parse_result(input: &str, expected: CfgExpr) {
101 let (tt, _) = get_token_tree_generated(input);
98 assert_eq!(parse_cfg(&tt), expected); 102 assert_eq!(parse_cfg(&tt), expected);
99 } 103 }
100 104
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
index f8f767091..482a2f3e6 100644
--- a/crates/ra_db/src/fixture.rs
+++ b/crates/ra_db/src/fixture.rs
@@ -63,7 +63,7 @@ use std::sync::Arc;
63 63
64use ra_cfg::CfgOptions; 64use ra_cfg::CfgOptions;
65use rustc_hash::FxHashMap; 65use rustc_hash::FxHashMap;
66use test_utils::{extract_offset, parse_fixture, parse_single_fixture, CURSOR_MARKER}; 66use test_utils::{extract_offset, parse_fixture, parse_single_fixture, FixtureMeta, CURSOR_MARKER};
67 67
68use crate::{ 68use crate::{
69 input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, 69 input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf,
@@ -113,7 +113,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
113 let fixture = parse_single_fixture(ra_fixture); 113 let fixture = parse_single_fixture(ra_fixture);
114 114
115 let crate_graph = if let Some(entry) = fixture { 115 let crate_graph = if let Some(entry) = fixture {
116 let meta = match parse_meta(&entry.meta) { 116 let meta = match ParsedMeta::from(&entry.meta) {
117 ParsedMeta::File(it) => it, 117 ParsedMeta::File(it) => it,
118 _ => panic!("with_single_file only support file meta"), 118 _ => panic!("with_single_file only support file meta"),
119 }; 119 };
@@ -170,7 +170,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
170 let mut file_position = None; 170 let mut file_position = None;
171 171
172 for entry in fixture.iter() { 172 for entry in fixture.iter() {
173 let meta = match parse_meta(&entry.meta) { 173 let meta = match ParsedMeta::from(&entry.meta) {
174 ParsedMeta::Root { path } => { 174 ParsedMeta::Root { path } => {
175 let source_root = std::mem::replace(&mut source_root, SourceRoot::new_local()); 175 let source_root = std::mem::replace(&mut source_root, SourceRoot::new_local());
176 db.set_source_root(source_root_id, Arc::new(source_root)); 176 db.set_source_root(source_root_id, Arc::new(source_root));
@@ -258,53 +258,25 @@ struct FileMeta {
258 env: Env, 258 env: Env,
259} 259}
260 260
261//- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo) 261impl From<&FixtureMeta> for ParsedMeta {
262fn parse_meta(meta: &str) -> ParsedMeta { 262 fn from(meta: &FixtureMeta) -> Self {
263 let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); 263 match meta {
264 264 FixtureMeta::Root { path } => {
265 if components[0] == "root" { 265 // `Self::Root` causes a false warning: 'variant is never constructed: `Root` '
266 let path: RelativePathBuf = components[1].into(); 266 // see https://github.com/rust-lang/rust/issues/69018
267 assert!(path.starts_with("/") && path.ends_with("/")); 267 ParsedMeta::Root { path: path.to_owned() }
268 return ParsedMeta::Root { path };
269 }
270
271 let path: RelativePathBuf = components[0].into();
272 assert!(path.starts_with("/"));
273
274 let mut krate = None;
275 let mut deps = Vec::new();
276 let mut edition = Edition::Edition2018;
277 let mut cfg = CfgOptions::default();
278 let mut env = Env::default();
279 for component in components[1..].iter() {
280 let (key, value) = split1(component, ':').unwrap();
281 match key {
282 "crate" => krate = Some(value.to_string()),
283 "deps" => deps = value.split(',').map(|it| it.to_string()).collect(),
284 "edition" => edition = Edition::from_str(&value).unwrap(),
285 "cfg" => {
286 for key in value.split(',') {
287 match split1(key, '=') {
288 None => cfg.insert_atom(key.into()),
289 Some((k, v)) => cfg.insert_key_value(k.into(), v.into()),
290 }
291 }
292 }
293 "env" => {
294 for key in value.split(',') {
295 if let Some((k, v)) = split1(key, '=') {
296 env.set(k, v.into());
297 }
298 }
299 } 268 }
300 _ => panic!("bad component: {:?}", component), 269 FixtureMeta::File(f) => Self::File(FileMeta {
270 path: f.path.to_owned(),
271 krate: f.crate_name.to_owned(),
272 deps: f.deps.to_owned(),
273 cfg: f.cfg.to_owned(),
274 edition: f
275 .edition
276 .as_ref()
277 .map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()),
278 env: Env::from(f.env.iter()),
279 }),
301 } 280 }
302 } 281 }
303
304 ParsedMeta::File(FileMeta { path, krate, deps, edition, cfg, env })
305}
306
307fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> {
308 let idx = haystack.find(delim)?;
309 Some((&haystack[..idx], &haystack[idx + delim.len_utf8()..]))
310} 282}
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index ab14e2d5e..4d2d3b48a 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -311,6 +311,21 @@ impl fmt::Display for Edition {
311 } 311 }
312} 312}
313 313
314impl<'a, T> From<T> for Env
315where
316 T: Iterator<Item = (&'a String, &'a String)>,
317{
318 fn from(iter: T) -> Self {
319 let mut result = Self::default();
320
321 for (k, v) in iter {
322 result.entries.insert(k.to_owned(), v.to_owned());
323 }
324
325 result
326 }
327}
328
314impl Env { 329impl Env {
315 pub fn set(&mut self, env: &str, value: String) { 330 pub fn set(&mut self, env: &str, value: String) {
316 self.entries.insert(env.to_owned(), value); 331 self.entries.insert(env.to_owned(), value);
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 840cfdfc8..4a06f3bcd 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -532,7 +532,7 @@ impl Adt {
532 Some(self.module(db).krate()) 532 Some(self.module(db).krate())
533 } 533 }
534 534
535 pub fn name(&self, db: &dyn HirDatabase) -> Name { 535 pub fn name(self, db: &dyn HirDatabase) -> Name {
536 match self { 536 match self {
537 Adt::Struct(s) => s.name(db), 537 Adt::Struct(s) => s.name(db),
538 Adt::Union(u) => u.name(db), 538 Adt::Union(u) => u.name(db),
@@ -637,6 +637,10 @@ impl Function {
637 db.function_data(self.id).params.clone() 637 db.function_data(self.id).params.clone()
638 } 638 }
639 639
640 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
641 db.function_data(self.id).is_unsafe
642 }
643
640 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 644 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
641 let _p = profile("Function::diagnostics"); 645 let _p = profile("Function::diagnostics");
642 let infer = db.infer(self.id.into()); 646 let infer = db.infer(self.id.into());
@@ -1018,15 +1022,15 @@ impl ImplDef {
1018 impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() 1022 impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect()
1019 } 1023 }
1020 1024
1021 pub fn target_trait(&self, db: &dyn HirDatabase) -> Option<TypeRef> { 1025 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1022 db.impl_data(self.id).target_trait.clone() 1026 db.impl_data(self.id).target_trait.clone()
1023 } 1027 }
1024 1028
1025 pub fn target_type(&self, db: &dyn HirDatabase) -> TypeRef { 1029 pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef {
1026 db.impl_data(self.id).target_type.clone() 1030 db.impl_data(self.id).target_type.clone()
1027 } 1031 }
1028 1032
1029 pub fn target_ty(&self, db: &dyn HirDatabase) -> Type { 1033 pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
1030 let impl_data = db.impl_data(self.id); 1034 let impl_data = db.impl_data(self.id);
1031 let resolver = self.id.resolver(db.upcast()); 1035 let resolver = self.id.resolver(db.upcast());
1032 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 1036 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
@@ -1038,23 +1042,23 @@ impl ImplDef {
1038 } 1042 }
1039 } 1043 }
1040 1044
1041 pub fn items(&self, db: &dyn HirDatabase) -> Vec<AssocItem> { 1045 pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
1042 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect() 1046 db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
1043 } 1047 }
1044 1048
1045 pub fn is_negative(&self, db: &dyn HirDatabase) -> bool { 1049 pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
1046 db.impl_data(self.id).is_negative 1050 db.impl_data(self.id).is_negative
1047 } 1051 }
1048 1052
1049 pub fn module(&self, db: &dyn HirDatabase) -> Module { 1053 pub fn module(self, db: &dyn HirDatabase) -> Module {
1050 self.id.lookup(db.upcast()).container.module(db.upcast()).into() 1054 self.id.lookup(db.upcast()).container.module(db.upcast()).into()
1051 } 1055 }
1052 1056
1053 pub fn krate(&self, db: &dyn HirDatabase) -> Crate { 1057 pub fn krate(self, db: &dyn HirDatabase) -> Crate {
1054 Crate { id: self.module(db).id.krate } 1058 Crate { id: self.module(db).id.krate }
1055 } 1059 }
1056 1060
1057 pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { 1061 pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
1058 let src = self.source(db); 1062 let src = self.source(db);
1059 let item = src.file_id.is_builtin_derive(db.upcast())?; 1063 let item = src.file_id.is_builtin_derive(db.upcast())?;
1060 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); 1064 let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
@@ -1190,6 +1194,10 @@ impl Type {
1190 ) 1194 )
1191 } 1195 }
1192 1196
1197 pub fn is_raw_ptr(&self) -> bool {
1198 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
1199 }
1200
1193 pub fn contains_unknown(&self) -> bool { 1201 pub fn contains_unknown(&self) -> bool {
1194 return go(&self.ty.value); 1202 return go(&self.ty.value);
1195 1203
@@ -1363,6 +1371,7 @@ impl HirDisplay for Type {
1363} 1371}
1364 1372
1365/// For IDE only 1373/// For IDE only
1374#[derive(Debug)]
1366pub enum ScopeDef { 1375pub enum ScopeDef {
1367 ModuleDef(ModuleDef), 1376 ModuleDef(ModuleDef),
1368 MacroDef(MacroDef), 1377 MacroDef(MacroDef),
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 4af0f046a..f4a6b0503 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -62,6 +62,7 @@ pub use crate::{
62 62
63pub use hir_def::{ 63pub use hir_def::{
64 adt::StructKind, 64 adt::StructKind,
65 attr::Attrs,
65 body::scope::ExprScopes, 66 body::scope::ExprScopes,
66 builtin_type::BuiltinType, 67 builtin_type::BuiltinType,
67 docs::Documentation, 68 docs::Documentation,
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 576cd0c65..2eeba0572 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -81,18 +81,24 @@ impl Attrs {
81 } 81 }
82 } 82 }
83 83
84 fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { 84 pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
85 let hygiene = Hygiene::new(db.upcast(), owner.file_id); 85 let hygiene = Hygiene::new(db.upcast(), owner.file_id);
86 Attrs::new(owner.value, &hygiene) 86 Attrs::new(owner.value, &hygiene)
87 } 87 }
88 88
89 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { 89 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
90 let docs = ast::CommentIter::from_syntax_node(owner.syntax()).doc_comment_text().map(
91 |docs_text| Attr {
92 input: Some(AttrInput::Literal(SmolStr::new(docs_text))),
93 path: ModPath::from(hir_expand::name!(doc)),
94 },
95 );
90 let mut attrs = owner.attrs().peekable(); 96 let mut attrs = owner.attrs().peekable();
91 let entries = if attrs.peek().is_none() { 97 let entries = if attrs.peek().is_none() {
92 // Avoid heap allocation 98 // Avoid heap allocation
93 None 99 None
94 } else { 100 } else {
95 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect()) 101 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).chain(docs).collect())
96 }; 102 };
97 Attrs { entries } 103 Attrs { entries }
98 } 104 }
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index f5a7305dc..273036cee 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -29,7 +29,7 @@ use crate::{
29 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, 29 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
30}; 30};
31 31
32/// A subset of Exander that only deals with cfg attributes. We only need it to 32/// A subset of Expander that only deals with cfg attributes. We only need it to
33/// avoid cyclic queries in crate def map during enum processing. 33/// avoid cyclic queries in crate def map during enum processing.
34pub(crate) struct CfgExpander { 34pub(crate) struct CfgExpander {
35 cfg_options: CfgOptions, 35 cfg_options: CfgOptions,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e08d62dd6..f159f80af 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -28,7 +28,7 @@ use crate::{
28 }, 28 },
29 item_scope::BuiltinShadowMode, 29 item_scope::BuiltinShadowMode,
30 path::{GenericArgs, Path}, 30 path::{GenericArgs, Path},
31 type_ref::{Mutability, TypeRef}, 31 type_ref::{Mutability, Rawness, TypeRef},
32 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, 32 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
33 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 33 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
34}; 34};
@@ -134,7 +134,7 @@ impl ExprCollector<'_> {
134 self.make_expr(expr, Err(SyntheticSyntax)) 134 self.make_expr(expr, Err(SyntheticSyntax))
135 } 135 }
136 fn empty_block(&mut self) -> ExprId { 136 fn empty_block(&mut self) -> ExprId {
137 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 137 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None })
138 } 138 }
139 fn missing_expr(&mut self) -> ExprId { 139 fn missing_expr(&mut self) -> ExprId {
140 self.alloc_expr_desugared(Expr::Missing) 140 self.alloc_expr_desugared(Expr::Missing)
@@ -215,7 +215,16 @@ impl ExprCollector<'_> {
215 ast::Expr::BlockExpr(e) => self.collect_block(e), 215 ast::Expr::BlockExpr(e) => self.collect_block(e),
216 ast::Expr::LoopExpr(e) => { 216 ast::Expr::LoopExpr(e) => {
217 let body = self.collect_block_opt(e.loop_body()); 217 let body = self.collect_block_opt(e.loop_body());
218 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 218 self.alloc_expr(
219 Expr::Loop {
220 body,
221 label: e
222 .label()
223 .and_then(|l| l.lifetime_token())
224 .map(|l| Name::new_lifetime(&l)),
225 },
226 syntax_ptr,
227 )
219 } 228 }
220 ast::Expr::WhileExpr(e) => { 229 ast::Expr::WhileExpr(e) => {
221 let body = self.collect_block_opt(e.loop_body()); 230 let body = self.collect_block_opt(e.loop_body());
@@ -230,25 +239,56 @@ impl ExprCollector<'_> {
230 let pat = self.collect_pat(pat); 239 let pat = self.collect_pat(pat);
231 let match_expr = self.collect_expr_opt(condition.expr()); 240 let match_expr = self.collect_expr_opt(condition.expr());
232 let placeholder_pat = self.missing_pat(); 241 let placeholder_pat = self.missing_pat();
233 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); 242 let break_ =
243 self.alloc_expr_desugared(Expr::Break { expr: None, label: None });
234 let arms = vec![ 244 let arms = vec![
235 MatchArm { pat, expr: body, guard: None }, 245 MatchArm { pat, expr: body, guard: None },
236 MatchArm { pat: placeholder_pat, expr: break_, guard: None }, 246 MatchArm { pat: placeholder_pat, expr: break_, guard: None },
237 ]; 247 ];
238 let match_expr = 248 let match_expr =
239 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 249 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
240 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); 250 return self.alloc_expr(
251 Expr::Loop {
252 body: match_expr,
253 label: e
254 .label()
255 .and_then(|l| l.lifetime_token())
256 .map(|l| Name::new_lifetime(&l)),
257 },
258 syntax_ptr,
259 );
241 } 260 }
242 }, 261 },
243 }; 262 };
244 263
245 self.alloc_expr(Expr::While { condition, body }, syntax_ptr) 264 self.alloc_expr(
265 Expr::While {
266 condition,
267 body,
268 label: e
269 .label()
270 .and_then(|l| l.lifetime_token())
271 .map(|l| Name::new_lifetime(&l)),
272 },
273 syntax_ptr,
274 )
246 } 275 }
247 ast::Expr::ForExpr(e) => { 276 ast::Expr::ForExpr(e) => {
248 let iterable = self.collect_expr_opt(e.iterable()); 277 let iterable = self.collect_expr_opt(e.iterable());
249 let pat = self.collect_pat_opt(e.pat()); 278 let pat = self.collect_pat_opt(e.pat());
250 let body = self.collect_block_opt(e.loop_body()); 279 let body = self.collect_block_opt(e.loop_body());
251 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) 280 self.alloc_expr(
281 Expr::For {
282 iterable,
283 pat,
284 body,
285 label: e
286 .label()
287 .and_then(|l| l.lifetime_token())
288 .map(|l| Name::new_lifetime(&l)),
289 },
290 syntax_ptr,
291 )
252 } 292 }
253 ast::Expr::CallExpr(e) => { 293 ast::Expr::CallExpr(e) => {
254 let callee = self.collect_expr_opt(e.expr()); 294 let callee = self.collect_expr_opt(e.expr());
@@ -301,13 +341,16 @@ impl ExprCollector<'_> {
301 .unwrap_or(Expr::Missing); 341 .unwrap_or(Expr::Missing);
302 self.alloc_expr(path, syntax_ptr) 342 self.alloc_expr(path, syntax_ptr)
303 } 343 }
304 ast::Expr::ContinueExpr(_e) => { 344 ast::Expr::ContinueExpr(e) => self.alloc_expr(
305 // FIXME: labels 345 Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
306 self.alloc_expr(Expr::Continue, syntax_ptr) 346 syntax_ptr,
307 } 347 ),
308 ast::Expr::BreakExpr(e) => { 348 ast::Expr::BreakExpr(e) => {
309 let expr = e.expr().map(|e| self.collect_expr(e)); 349 let expr = e.expr().map(|e| self.collect_expr(e));
310 self.alloc_expr(Expr::Break { expr }, syntax_ptr) 350 self.alloc_expr(
351 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
352 syntax_ptr,
353 )
311 } 354 }
312 ast::Expr::ParenExpr(e) => { 355 ast::Expr::ParenExpr(e) => {
313 let inner = self.collect_expr_opt(e.expr()); 356 let inner = self.collect_expr_opt(e.expr());
@@ -378,8 +421,21 @@ impl ExprCollector<'_> {
378 } 421 }
379 ast::Expr::RefExpr(e) => { 422 ast::Expr::RefExpr(e) => {
380 let expr = self.collect_expr_opt(e.expr()); 423 let expr = self.collect_expr_opt(e.expr());
381 let mutability = Mutability::from_mutable(e.mut_token().is_some()); 424 let raw_tok = e.raw_token().is_some();
382 self.alloc_expr(Expr::Ref { expr, mutability }, syntax_ptr) 425 let mutability = if raw_tok {
426 if e.mut_token().is_some() {
427 Mutability::Mut
428 } else if e.const_token().is_some() {
429 Mutability::Shared
430 } else {
431 unreachable!("parser only remaps to raw_token() if matching mutability token follows")
432 }
433 } else {
434 Mutability::from_mutable(e.mut_token().is_some())
435 };
436 let rawness = Rawness::from_raw(raw_tok);
437
438 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
383 } 439 }
384 ast::Expr::PrefixExpr(e) => { 440 ast::Expr::PrefixExpr(e) => {
385 let expr = self.collect_expr_opt(e.expr()); 441 let expr = self.collect_expr_opt(e.expr());
@@ -516,7 +572,8 @@ impl ExprCollector<'_> {
516 }) 572 })
517 .collect(); 573 .collect();
518 let tail = block.expr().map(|e| self.collect_expr(e)); 574 let tail = block.expr().map(|e| self.collect_expr(e));
519 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 575 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
576 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
520 } 577 }
521 578
522 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 579 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 09e92b74e..e48ff38f9 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -138,10 +138,10 @@ fn compute_block_scopes(
138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
139 scopes.set_scope(expr, scope); 139 scopes.set_scope(expr, scope);
140 match &body[expr] { 140 match &body[expr] {
141 Expr::Block { statements, tail } => { 141 Expr::Block { statements, tail, .. } => {
142 compute_block_scopes(&statements, *tail, body, scopes, scope); 142 compute_block_scopes(&statements, *tail, body, scopes, scope);
143 } 143 }
144 Expr::For { iterable, pat, body: body_expr } => { 144 Expr::For { iterable, pat, body: body_expr, .. } => {
145 compute_expr_scopes(*iterable, body, scopes, scope); 145 compute_expr_scopes(*iterable, body, scopes, scope);
146 let scope = scopes.new_scope(scope); 146 let scope = scopes.new_scope(scope);
147 scopes.add_bindings(body, scope, *pat); 147 scopes.add_bindings(body, scope, *pat);
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index e2130d931..807195d25 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -34,6 +34,7 @@ pub struct FunctionData {
34 /// True if the first param is `self`. This is relevant to decide whether this 34 /// True if the first param is `self`. This is relevant to decide whether this
35 /// can be called as a method. 35 /// can be called as a method.
36 pub has_self_param: bool, 36 pub has_self_param: bool,
37 pub is_unsafe: bool,
37 pub visibility: RawVisibility, 38 pub visibility: RawVisibility,
38} 39}
39 40
@@ -85,11 +86,14 @@ impl FunctionData {
85 ret_type 86 ret_type
86 }; 87 };
87 88
89 let is_unsafe = src.value.unsafe_token().is_some();
90
88 let vis_default = RawVisibility::default_for_container(loc.container); 91 let vis_default = RawVisibility::default_for_container(loc.container);
89 let visibility = 92 let visibility =
90 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); 93 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
91 94
92 let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; 95 let sig =
96 FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
93 Arc::new(sig) 97 Arc::new(sig)
94 } 98 }
95} 99}
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index b221ae1ce..2630b3d89 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -29,6 +29,13 @@ impl Documentation {
29 Documentation(s.into()) 29 Documentation(s.into())
30 } 30 }
31 31
32 pub fn from_ast<N>(node: &N) -> Option<Documentation>
33 where
34 N: ast::DocCommentsOwner + ast::AttrsOwner,
35 {
36 docs_from_ast(node)
37 }
38
32 pub fn as_str(&self) -> &str { 39 pub fn as_str(&self) -> &str {
33 &*self.0 40 &*self.0
34 } 41 }
@@ -70,6 +77,45 @@ impl Documentation {
70 } 77 }
71} 78}
72 79
73pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> { 80pub(crate) fn docs_from_ast<N>(node: &N) -> Option<Documentation>
74 node.doc_comment_text().map(|it| Documentation::new(&it)) 81where
82 N: ast::DocCommentsOwner + ast::AttrsOwner,
83{
84 let doc_comment_text = node.doc_comment_text();
85 let doc_attr_text = expand_doc_attrs(node);
86 let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text);
87 docs.map(|it| Documentation::new(&it))
88}
89
90fn merge_doc_comments_and_attrs(
91 doc_comment_text: Option<String>,
92 doc_attr_text: Option<String>,
93) -> Option<String> {
94 match (doc_comment_text, doc_attr_text) {
95 (Some(mut comment_text), Some(attr_text)) => {
96 comment_text.push_str("\n\n");
97 comment_text.push_str(&attr_text);
98 Some(comment_text)
99 }
100 (Some(comment_text), None) => Some(comment_text),
101 (None, Some(attr_text)) => Some(attr_text),
102 (None, None) => None,
103 }
104}
105
106fn expand_doc_attrs(owner: &dyn ast::AttrsOwner) -> Option<String> {
107 let mut docs = String::new();
108 for attr in owner.attrs() {
109 if let Some(("doc", value)) =
110 attr.as_simple_key_value().as_ref().map(|(k, v)| (k.as_str(), v.as_str()))
111 {
112 docs.push_str(value);
113 docs.push_str("\n\n");
114 }
115 }
116 if docs.is_empty() {
117 None
118 } else {
119 Some(docs.trim_end_matches("\n\n").to_owned())
120 }
75} 121}
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index a0cdad529..ca49b26d1 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -19,7 +19,7 @@ use ra_syntax::ast::RangeOp;
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt}, 20 builtin_type::{BuiltinFloat, BuiltinInt},
21 path::{GenericArgs, Path}, 21 path::{GenericArgs, Path},
22 type_ref::{Mutability, TypeRef}, 22 type_ref::{Mutability, Rawness, TypeRef},
23}; 23};
24 24
25pub type ExprId = Idx<Expr>; 25pub type ExprId = Idx<Expr>;
@@ -52,18 +52,22 @@ pub enum Expr {
52 Block { 52 Block {
53 statements: Vec<Statement>, 53 statements: Vec<Statement>,
54 tail: Option<ExprId>, 54 tail: Option<ExprId>,
55 label: Option<Name>,
55 }, 56 },
56 Loop { 57 Loop {
57 body: ExprId, 58 body: ExprId,
59 label: Option<Name>,
58 }, 60 },
59 While { 61 While {
60 condition: ExprId, 62 condition: ExprId,
61 body: ExprId, 63 body: ExprId,
64 label: Option<Name>,
62 }, 65 },
63 For { 66 For {
64 iterable: ExprId, 67 iterable: ExprId,
65 pat: PatId, 68 pat: PatId,
66 body: ExprId, 69 body: ExprId,
70 label: Option<Name>,
67 }, 71 },
68 Call { 72 Call {
69 callee: ExprId, 73 callee: ExprId,
@@ -79,9 +83,12 @@ pub enum Expr {
79 expr: ExprId, 83 expr: ExprId,
80 arms: Vec<MatchArm>, 84 arms: Vec<MatchArm>,
81 }, 85 },
82 Continue, 86 Continue {
87 label: Option<Name>,
88 },
83 Break { 89 Break {
84 expr: Option<ExprId>, 90 expr: Option<ExprId>,
91 label: Option<Name>,
85 }, 92 },
86 Return { 93 Return {
87 expr: Option<ExprId>, 94 expr: Option<ExprId>,
@@ -110,6 +117,7 @@ pub enum Expr {
110 }, 117 },
111 Ref { 118 Ref {
112 expr: ExprId, 119 expr: ExprId,
120 rawness: Rawness,
113 mutability: Mutability, 121 mutability: Mutability,
114 }, 122 },
115 Box { 123 Box {
@@ -224,7 +232,7 @@ impl Expr {
224 f(*else_branch); 232 f(*else_branch);
225 } 233 }
226 } 234 }
227 Expr::Block { statements, tail } => { 235 Expr::Block { statements, tail, .. } => {
228 for stmt in statements { 236 for stmt in statements {
229 match stmt { 237 match stmt {
230 Statement::Let { initializer, .. } => { 238 Statement::Let { initializer, .. } => {
@@ -240,8 +248,8 @@ impl Expr {
240 } 248 }
241 } 249 }
242 Expr::TryBlock { body } => f(*body), 250 Expr::TryBlock { body } => f(*body),
243 Expr::Loop { body } => f(*body), 251 Expr::Loop { body, .. } => f(*body),
244 Expr::While { condition, body } => { 252 Expr::While { condition, body, .. } => {
245 f(*condition); 253 f(*condition);
246 f(*body); 254 f(*body);
247 } 255 }
@@ -267,8 +275,8 @@ impl Expr {
267 f(arm.expr); 275 f(arm.expr);
268 } 276 }
269 } 277 }
270 Expr::Continue => {} 278 Expr::Continue { .. } => {}
271 Expr::Break { expr } | Expr::Return { expr } => { 279 Expr::Break { expr, .. } | Expr::Return { expr } => {
272 if let Some(expr) = expr { 280 if let Some(expr) = expr {
273 f(*expr); 281 f(*expr);
274 } 282 }
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index d962db3cc..3516784b8 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -164,7 +164,7 @@ impl LangItems {
164 T: Into<AttrDefId> + Copy, 164 T: Into<AttrDefId> + Copy,
165 { 165 {
166 if let Some(lang_item_name) = lang_attr(db, item) { 166 if let Some(lang_item_name) = lang_attr(db, item) {
167 self.items.entry(lang_item_name.clone()).or_insert_with(|| constructor(item)); 167 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
168 } 168 }
169 } 169 }
170} 170}
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 4e628b14d..f44baa579 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -175,7 +175,7 @@ pub(super) enum DefKind {
175} 175}
176 176
177impl DefKind { 177impl DefKind {
178 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { 178 pub fn ast_id(self) -> FileAstId<ast::ModuleItem> {
179 match self { 179 match self {
180 DefKind::Function(it) => it.upcast(), 180 DefKind::Function(it) => it.upcast(),
181 DefKind::Struct(it, _) => it.upcast(), 181 DefKind::Struct(it, _) => it.upcast(),
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index 5bdad9efd..86a77b704 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -35,6 +35,22 @@ impl Mutability {
35 } 35 }
36} 36}
37 37
38#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
39pub enum Rawness {
40 RawPtr,
41 Ref,
42}
43
44impl Rawness {
45 pub fn from_raw(is_raw: bool) -> Rawness {
46 if is_raw {
47 Rawness::RawPtr
48 } else {
49 Rawness::Ref
50 }
51 }
52}
53
38/// Compare ty::Ty 54/// Compare ty::Ty
39#[derive(Clone, PartialEq, Eq, Hash, Debug)] 55#[derive(Clone, PartialEq, Eq, Hash, Debug)]
40pub enum TypeRef { 56pub enum TypeRef {
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index fecce224e..660bdfe33 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -37,6 +37,11 @@ impl Name {
37 Name(Repr::TupleField(idx)) 37 Name(Repr::TupleField(idx))
38 } 38 }
39 39
40 pub fn new_lifetime(lt: &ra_syntax::SyntaxToken) -> Name {
41 assert!(lt.kind() == ra_syntax::SyntaxKind::LIFETIME);
42 Name(Repr::Text(lt.text().clone()))
43 }
44
40 /// Shortcut to create inline plain text name 45 /// Shortcut to create inline plain text name
41 const fn new_inline_ascii(text: &[u8]) -> Name { 46 const fn new_inline_ascii(text: &[u8]) -> Name {
42 Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text)) 47 Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text))
@@ -148,6 +153,7 @@ pub mod known {
148 str, 153 str,
149 // Special names 154 // Special names
150 macro_rules, 155 macro_rules,
156 doc,
151 // Components of known path (value or mod name) 157 // Components of known path (value or mod name)
152 std, 158 std,
153 core, 159 core,
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs
index 4e0e069c8..04c026004 100644
--- a/crates/ra_hir_expand/src/proc_macro.rs
+++ b/crates/ra_hir_expand/src/proc_macro.rs
@@ -25,7 +25,7 @@ impl ProcMacroExpander {
25 } 25 }
26 26
27 pub fn expand( 27 pub fn expand(
28 &self, 28 self,
29 db: &dyn AstDatabase, 29 db: &dyn AstDatabase,
30 _id: LazyMacroId, 30 _id: LazyMacroId,
31 tt: &tt::Subtree, 31 tt: &tt::Subtree,
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index b2de7fa34..4b8dcdc07 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -27,9 +27,8 @@ test_utils = { path = "../test_utils" }
27 27
28scoped-tls = "1" 28scoped-tls = "1"
29 29
30chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "eaab84b394007d1bed15f5470409a6ea02900a96" } 30chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "329b7f3fdd2431ed6f6778cde53f22374c7d094c" }
31chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "eaab84b394007d1bed15f5470409a6ea02900a96" } 31chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "329b7f3fdd2431ed6f6778cde53f22374c7d094c" }
32chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "eaab84b394007d1bed15f5470409a6ea02900a96" }
33 32
34[dev-dependencies] 33[dev-dependencies]
35insta = "0.16.0" 34insta = "0.16.0"
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index dfc6c7dd6..0a8bb24ac 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -76,6 +76,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
76 #[salsa::interned] 76 #[salsa::interned]
77 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId; 77 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
78 #[salsa::interned] 78 #[salsa::interned]
79 fn intern_callable_def(&self, callable_def: CallableDef) -> crate::CallableDefId;
80 #[salsa::interned]
79 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; 81 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
80 #[salsa::interned] 82 #[salsa::interned]
81 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; 83 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
@@ -94,6 +96,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
94 #[salsa::invoke(crate::traits::chalk::impl_datum_query)] 96 #[salsa::invoke(crate::traits::chalk::impl_datum_query)]
95 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; 97 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>;
96 98
99 #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)]
100 fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>;
101
97 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] 102 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
98 fn associated_ty_value( 103 fn associated_ty_value(
99 &self, 104 &self,
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 41ac70272..2c7298714 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -40,7 +40,7 @@ impl Diagnostic for MissingFields {
40 fn message(&self) -> String { 40 fn message(&self) -> String {
41 let mut buf = String::from("Missing structure fields:\n"); 41 let mut buf = String::from("Missing structure fields:\n");
42 for field in &self.missed_fields { 42 for field in &self.missed_fields {
43 format_to!(buf, "- {}", field); 43 format_to!(buf, "- {}\n", field);
44 } 44 }
45 buf 45 buf
46 } 46 }
@@ -73,7 +73,7 @@ impl Diagnostic for MissingPatFields {
73 fn message(&self) -> String { 73 fn message(&self) -> String {
74 let mut buf = String::from("Missing structure fields:\n"); 74 let mut buf = String::from("Missing structure fields:\n");
75 for field in &self.missed_fields { 75 for field in &self.missed_fields {
76 format_to!(buf, "- {}", field); 76 format_to!(buf, "- {}\n", field);
77 } 77 }
78 buf 78 buf
79 } 79 }
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 957d6e0b5..dc77e88e5 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -219,6 +219,17 @@ struct InferenceContext<'a> {
219struct BreakableContext { 219struct BreakableContext {
220 pub may_break: bool, 220 pub may_break: bool,
221 pub break_ty: Ty, 221 pub break_ty: Ty,
222 pub label: Option<name::Name>,
223}
224
225fn find_breakable<'c>(
226 ctxs: &'c mut [BreakableContext],
227 label: Option<&name::Name>,
228) -> Option<&'c mut BreakableContext> {
229 match label {
230 Some(_) => ctxs.iter_mut().rev().find(|ctx| ctx.label.as_ref() == label),
231 None => ctxs.last_mut(),
232 }
222} 233}
223 234
224impl<'a> InferenceContext<'a> { 235impl<'a> InferenceContext<'a> {
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 2ee9adb16..32c7c57cd 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -45,9 +45,7 @@ impl<'a> InferenceContext<'a> {
45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) 45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
46 } else { 46 } else {
47 mark::hit!(coerce_merge_fail_fallback); 47 mark::hit!(coerce_merge_fail_fallback);
48 // For incompatible types, we use the latter one as result 48 ty1.clone()
49 // to be better recovery for `if` without `else`.
50 ty2.clone()
51 } 49 }
52 } 50 }
53 } 51 }
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index b28724f0e..4a98e2deb 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -17,13 +17,13 @@ use crate::{
17 autoderef, method_resolution, op, 17 autoderef, method_resolution, op,
18 traits::InEnvironment, 18 traits::InEnvironment,
19 utils::{generics, variant_data, Generics}, 19 utils::{generics, variant_data, Generics},
20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, 20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
21 Ty, TypeCtor, Uncertain, 21 TraitRef, Ty, TypeCtor, Uncertain,
22}; 22};
23 23
24use super::{ 24use super::{
25 BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic, 25 find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext,
26 TypeMismatch, 26 InferenceDiagnostic, TypeMismatch,
27}; 27};
28 28
29impl<'a> InferenceContext<'a> { 29impl<'a> InferenceContext<'a> {
@@ -86,16 +86,20 @@ impl<'a> InferenceContext<'a> {
86 86
87 self.coerce_merge_branch(&then_ty, &else_ty) 87 self.coerce_merge_branch(&then_ty, &else_ty)
88 } 88 }
89 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), 89 Expr::Block { statements, tail, .. } => {
90 // FIXME: Breakable block inference
91 self.infer_block(statements, *tail, expected)
92 }
90 Expr::TryBlock { body } => { 93 Expr::TryBlock { body } => {
91 let _inner = self.infer_expr(*body, expected); 94 let _inner = self.infer_expr(*body, expected);
92 // FIXME should be std::result::Result<{inner}, _> 95 // FIXME should be std::result::Result<{inner}, _>
93 Ty::Unknown 96 Ty::Unknown
94 } 97 }
95 Expr::Loop { body } => { 98 Expr::Loop { body, label } => {
96 self.breakables.push(BreakableContext { 99 self.breakables.push(BreakableContext {
97 may_break: false, 100 may_break: false,
98 break_ty: self.table.new_type_var(), 101 break_ty: self.table.new_type_var(),
102 label: label.clone(),
99 }); 103 });
100 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 104 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
101 105
@@ -110,8 +114,12 @@ impl<'a> InferenceContext<'a> {
110 Ty::simple(TypeCtor::Never) 114 Ty::simple(TypeCtor::Never)
111 } 115 }
112 } 116 }
113 Expr::While { condition, body } => { 117 Expr::While { condition, body, label } => {
114 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); 118 self.breakables.push(BreakableContext {
119 may_break: false,
120 break_ty: Ty::Unknown,
121 label: label.clone(),
122 });
115 // while let is desugared to a match loop, so this is always simple while 123 // while let is desugared to a match loop, so this is always simple while
116 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 124 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
117 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 125 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
@@ -120,10 +128,14 @@ impl<'a> InferenceContext<'a> {
120 self.diverges = Diverges::Maybe; 128 self.diverges = Diverges::Maybe;
121 Ty::unit() 129 Ty::unit()
122 } 130 }
123 Expr::For { iterable, body, pat } => { 131 Expr::For { iterable, body, pat, label } => {
124 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 132 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
125 133
126 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); 134 self.breakables.push(BreakableContext {
135 may_break: false,
136 break_ty: Ty::Unknown,
137 label: label.clone(),
138 });
127 let pat_ty = 139 let pat_ty =
128 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); 140 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
129 141
@@ -140,13 +152,13 @@ impl<'a> InferenceContext<'a> {
140 152
141 let mut sig_tys = Vec::new(); 153 let mut sig_tys = Vec::new();
142 154
143 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { 155 // collect explicitly written argument types
144 let expected = if let Some(type_ref) = arg_type { 156 for arg_type in arg_types.iter() {
157 let arg_ty = if let Some(type_ref) = arg_type {
145 self.make_ty(type_ref) 158 self.make_ty(type_ref)
146 } else { 159 } else {
147 Ty::Unknown 160 self.table.new_type_var()
148 }; 161 };
149 let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default());
150 sig_tys.push(arg_ty); 162 sig_tys.push(arg_ty);
151 } 163 }
152 164
@@ -158,7 +170,7 @@ impl<'a> InferenceContext<'a> {
158 sig_tys.push(ret_ty.clone()); 170 sig_tys.push(ret_ty.clone());
159 let sig_ty = Ty::apply( 171 let sig_ty = Ty::apply(
160 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 172 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
161 Substs(sig_tys.into()), 173 Substs(sig_tys.clone().into()),
162 ); 174 );
163 let closure_ty = 175 let closure_ty =
164 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); 176 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty);
@@ -168,6 +180,12 @@ impl<'a> InferenceContext<'a> {
168 // infer the body. 180 // infer the body.
169 self.coerce(&closure_ty, &expected.ty); 181 self.coerce(&closure_ty, &expected.ty);
170 182
183 // Now go through the argument patterns
184 for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
185 let resolved = self.resolve_ty_as_possible(arg_ty);
186 self.infer_pat(*arg_pat, &resolved, BindingMode::default());
187 }
188
171 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); 189 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
172 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); 190 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
173 191
@@ -230,23 +248,24 @@ impl<'a> InferenceContext<'a> {
230 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); 248 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
231 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) 249 self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown)
232 } 250 }
233 Expr::Continue => Ty::simple(TypeCtor::Never), 251 Expr::Continue { .. } => Ty::simple(TypeCtor::Never),
234 Expr::Break { expr } => { 252 Expr::Break { expr, label } => {
235 let val_ty = if let Some(expr) = expr { 253 let val_ty = if let Some(expr) = expr {
236 self.infer_expr(*expr, &Expectation::none()) 254 self.infer_expr(*expr, &Expectation::none())
237 } else { 255 } else {
238 Ty::unit() 256 Ty::unit()
239 }; 257 };
240 258
241 let last_ty = if let Some(ctxt) = self.breakables.last() { 259 let last_ty =
242 ctxt.break_ty.clone() 260 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
243 } else { 261 ctxt.break_ty.clone()
244 Ty::Unknown 262 } else {
245 }; 263 Ty::Unknown
264 };
246 265
247 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); 266 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
248 267
249 if let Some(ctxt) = self.breakables.last_mut() { 268 if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) {
250 ctxt.break_ty = merged_type; 269 ctxt.break_ty = merged_type;
251 ctxt.may_break = true; 270 ctxt.may_break = true;
252 } else { 271 } else {
@@ -350,19 +369,28 @@ impl<'a> InferenceContext<'a> {
350 // FIXME check the cast... 369 // FIXME check the cast...
351 cast_ty 370 cast_ty
352 } 371 }
353 Expr::Ref { expr, mutability } => { 372 Expr::Ref { expr, rawness, mutability } => {
354 let expectation = 373 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) =
355 if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { 374 &expected.ty.as_reference_or_ptr()
356 if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { 375 {
357 // FIXME: throw type error - expected mut reference but found shared ref, 376 if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared {
358 // which cannot be coerced 377 // FIXME: throw type error - expected mut reference but found shared ref,
359 } 378 // which cannot be coerced
360 Expectation::rvalue_hint(Ty::clone(exp_inner)) 379 }
361 } else { 380 if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
362 Expectation::none() 381 // FIXME: throw type error - expected reference but found ptr,
363 }; 382 // which cannot be coerced
383 }
384 Expectation::rvalue_hint(Ty::clone(exp_inner))
385 } else {
386 Expectation::none()
387 };
364 let inner_ty = self.infer_expr_inner(*expr, &expectation); 388 let inner_ty = self.infer_expr_inner(*expr, &expectation);
365 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 389 let ty = match rawness {
390 Rawness::RawPtr => TypeCtor::RawPtr(*mutability),
391 Rawness::Ref => TypeCtor::Ref(*mutability),
392 };
393 Ty::apply_one(ty, inner_ty)
366 } 394 }
367 Expr::Box { expr } => { 395 Expr::Box { expr } => {
368 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 396 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index e91c9be04..9fa8d3bdc 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -49,8 +49,10 @@ use std::sync::Arc;
49use std::{iter, mem}; 49use std::{iter, mem};
50 50
51use hir_def::{ 51use hir_def::{
52 expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, 52 expr::ExprId,
53 HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, 53 type_ref::{Mutability, Rawness},
54 AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
55 TypeParamId,
54}; 56};
55use ra_db::{impl_intern_key, salsa, CrateId}; 57use ra_db::{impl_intern_key, salsa, CrateId};
56 58
@@ -159,6 +161,12 @@ pub enum TypeCtor {
159pub struct TypeCtorId(salsa::InternId); 161pub struct TypeCtorId(salsa::InternId);
160impl_intern_key!(TypeCtorId); 162impl_intern_key!(TypeCtorId);
161 163
164/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
165/// we have different IDs for struct and enum variant constructors.
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
167pub struct CallableDefId(salsa::InternId);
168impl_intern_key!(CallableDefId);
169
162impl TypeCtor { 170impl TypeCtor {
163 pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize { 171 pub fn num_ty_params(self, db: &dyn HirDatabase) -> usize {
164 match self { 172 match self {
@@ -703,6 +711,18 @@ impl Ty {
703 } 711 }
704 } 712 }
705 713
714 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
715 match self {
716 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => {
717 Some((parameters.as_single(), Rawness::Ref, *mutability))
718 }
719 Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(mutability), parameters }) => {
720 Some((parameters.as_single(), Rawness::RawPtr, *mutability))
721 }
722 _ => None,
723 }
724 }
725
706 pub fn strip_references(&self) -> &Ty { 726 pub fn strip_references(&self) -> &Ty {
707 let mut t: &Ty = self; 727 let mut t: &Ty = self;
708 728
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 2cc4f4bf9..6f777ed8c 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -116,15 +116,20 @@ fn infer_let_stmt_coerce() {
116 assert_snapshot!( 116 assert_snapshot!(
117 infer(r#" 117 infer(r#"
118fn test() { 118fn test() {
119 let x: &[i32] = &[1]; 119 let x: &[isize] = &[1];
120 let x: *const [isize] = &[1];
120} 121}
121"#), 122"#),
122 @r###" 123 @r###"
123 11..40 '{ ...[1]; }': () 124 11..76 '{ ...[1]; }': ()
124 21..22 'x': &[i32] 125 21..22 'x': &[isize]
125 33..37 '&[1]': &[i32; _] 126 35..39 '&[1]': &[isize; _]
126 34..37 '[1]': [i32; _] 127 36..39 '[1]': [isize; _]
127 35..36 '1': i32 128 37..38 '1': isize
129 49..50 'x': *const [isize]
130 69..73 '&[1]': &[isize; _]
131 70..73 '[1]': [isize; _]
132 71..72 '1': isize
128 "###); 133 "###);
129} 134}
130 135
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index 0c5f972a2..fe62587c0 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -520,3 +520,53 @@ fn main() {
520 105..107 '()': () 520 105..107 '()': ()
521 ") 521 ")
522} 522}
523
524#[test]
525fn match_ergonomics_in_closure_params() {
526 assert_snapshot!(
527 infer(r#"
528#[lang = "fn_once"]
529trait FnOnce<Args> {
530 type Output;
531}
532
533fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} }
534
535fn test() {
536 foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics
537 foo(&(1, "a"), |(x, y)| x);
538}
539"#),
540 @r###"
541 94..95 't': T
542 100..101 'f': F
543 111..122 '{ loop {} }': U
544 113..120 'loop {}': !
545 118..120 '{}': ()
546 134..233 '{ ... x); }': ()
547 140..143 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32
548 140..167 'foo(&(...y)| x)': i32
549 144..153 '&(1, "a")': &(i32, &str)
550 145..153 '(1, "a")': (i32, &str)
551 146..147 '1': i32
552 149..152 '"a"': &str
553 155..166 '|&(x, y)| x': |&(i32, &str)| -> i32
554 156..163 '&(x, y)': &(i32, &str)
555 157..163 '(x, y)': (i32, &str)
556 158..159 'x': i32
557 161..162 'y': &str
558 165..166 'x': i32
559 204..207 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32
560 204..230 'foo(&(...y)| x)': &i32
561 208..217 '&(1, "a")': &(i32, &str)
562 209..217 '(1, "a")': (i32, &str)
563 210..211 '1': i32
564 213..216 '"a"': &str
565 219..229 '|(x, y)| x': |&(i32, &str)| -> &i32
566 220..226 '(x, y)': (i32, &str)
567 221..222 'x': &i32
568 224..225 'y': &&str
569 228..229 'x': &i32
570 "###
571 );
572}
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index fd2208af2..88309157b 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -385,6 +385,26 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
385} 385}
386 386
387#[test] 387#[test]
388fn infer_raw_ref() {
389 assert_snapshot!(
390 infer(r#"
391fn test(a: i32) {
392 &raw mut a;
393 &raw const a;
394}
395"#),
396 @r###"
397 9..10 'a': i32
398 17..54 '{ ...t a; }': ()
399 23..33 '&raw mut a': *mut i32
400 32..33 'a': i32
401 39..51 '&raw const a': *const i32
402 50..51 'a': i32
403 "###
404 );
405}
406
407#[test]
388fn infer_literals() { 408fn infer_literals() {
389 assert_snapshot!( 409 assert_snapshot!(
390 infer(r##" 410 infer(r##"
@@ -937,7 +957,7 @@ fn main(foo: Foo) {
937 51..107 'if tru... }': () 957 51..107 'if tru... }': ()
938 54..58 'true': bool 958 54..58 'true': bool
939 59..67 '{ }': () 959 59..67 '{ }': ()
940 73..107 'if fal... }': () 960 73..107 'if fal... }': i32
941 76..81 'false': bool 961 76..81 'false': bool
942 82..107 '{ ... }': i32 962 82..107 '{ ... }': i32
943 92..95 'foo': Foo 963 92..95 'foo': Foo
@@ -1923,3 +1943,57 @@ fn test() {
1923 "### 1943 "###
1924 ); 1944 );
1925} 1945}
1946
1947#[test]
1948fn infer_labelled_break_with_val() {
1949 assert_snapshot!(
1950 infer(r#"
1951fn foo() {
1952 let _x = || 'outer: loop {
1953 let inner = 'inner: loop {
1954 let i = Default::default();
1955 if (break 'outer i) {
1956 loop { break 'inner 5i8; };
1957 } else if true {
1958 break 'inner 6;
1959 }
1960 break 7;
1961 };
1962 break inner < 8;
1963 };
1964}
1965"#),
1966 @r###"
1967 10..336 '{ ... }; }': ()
1968 20..22 '_x': || -> bool
1969 25..333 '|| 'ou... }': || -> bool
1970 28..333 ''outer... }': bool
1971 41..333 '{ ... }': ()
1972 55..60 'inner': i8
1973 63..301 ''inner... }': i8
1974 76..301 '{ ... }': ()
1975 94..95 'i': bool
1976 98..114 'Defaul...efault': {unknown}
1977 98..116 'Defaul...ault()': bool
1978 130..270 'if (br... }': ()
1979 134..148 'break 'outer i': !
1980 147..148 'i': bool
1981 150..209 '{ ... }': ()
1982 168..194 'loop {...5i8; }': !
1983 173..194 '{ brea...5i8; }': ()
1984 175..191 'break ...er 5i8': !
1985 188..191 '5i8': i8
1986 215..270 'if tru... }': ()
1987 218..222 'true': bool
1988 223..270 '{ ... }': ()
1989 241..255 'break 'inner 6': !
1990 254..255 '6': i8
1991 283..290 'break 7': !
1992 289..290 '7': i8
1993 311..326 'break inner < 8': !
1994 317..322 'inner': i8
1995 317..326 'inner < 8': bool
1996 325..326 '8': i8
1997 "###
1998 );
1999}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 6826610cb..e8778d419 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -2644,6 +2644,79 @@ fn test() {
2644} 2644}
2645 2645
2646#[test] 2646#[test]
2647fn builtin_fn_def_copy() {
2648 assert_snapshot!(
2649 infer_with_mismatches(r#"
2650#[lang = "copy"]
2651trait Copy {}
2652
2653fn foo() {}
2654fn bar<T: Copy>(T) -> T {}
2655struct Struct(usize);
2656enum Enum { Variant(usize) }
2657
2658trait Test { fn test(&self) -> bool; }
2659impl<T: Copy> Test for T {}
2660
2661fn test() {
2662 foo.test();
2663 bar.test();
2664 Struct.test();
2665 Enum::Variant.test();
2666}
2667"#, true),
2668 @r###"
2669 42..44 '{}': ()
2670 61..62 'T': {unknown}
2671 69..71 '{}': ()
2672 69..71: expected T, got ()
2673 146..150 'self': &Self
2674 202..282 '{ ...t(); }': ()
2675 208..211 'foo': fn foo()
2676 208..218 'foo.test()': bool
2677 224..227 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
2678 224..234 'bar.test()': bool
2679 240..246 'Struct': Struct(usize) -> Struct
2680 240..253 'Struct.test()': bool
2681 259..272 'Enum::Variant': Variant(usize) -> Enum
2682 259..279 'Enum::...test()': bool
2683 "###
2684 );
2685}
2686
2687#[test]
2688fn builtin_fn_ptr_copy() {
2689 assert_snapshot!(
2690 infer_with_mismatches(r#"
2691#[lang = "copy"]
2692trait Copy {}
2693
2694trait Test { fn test(&self) -> bool; }
2695impl<T: Copy> Test for T {}
2696
2697fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
2698 f1.test();
2699 f2.test();
2700 f3.test();
2701}
2702"#, true),
2703 @r###"
2704 55..59 'self': &Self
2705 109..111 'f1': fn()
2706 119..121 'f2': fn(usize) -> u8
2707 140..142 'f3': fn(u8, u8) -> &u8
2708 163..211 '{ ...t(); }': ()
2709 169..171 'f1': fn()
2710 169..178 'f1.test()': bool
2711 184..186 'f2': fn(usize) -> u8
2712 184..193 'f2.test()': bool
2713 199..201 'f3': fn(u8, u8) -> &u8
2714 199..208 'f3.test()': bool
2715 "###
2716 );
2717}
2718
2719#[test]
2647fn builtin_sized() { 2720fn builtin_sized() {
2648 assert_snapshot!( 2721 assert_snapshot!(
2649 infer_with_mismatches(r#" 2722 infer_with_mismatches(r#"
@@ -2680,3 +2753,48 @@ fn test() {
2680 "### 2753 "###
2681 ); 2754 );
2682} 2755}
2756
2757#[test]
2758fn integer_range_iterate() {
2759 let t = type_at(
2760 r#"
2761//- /main.rs crate:main deps:std
2762fn test() {
2763 for x in 0..100 { x<|>; }
2764}
2765
2766//- /std.rs crate:std
2767pub mod ops {
2768 pub struct Range<Idx> {
2769 pub start: Idx,
2770 pub end: Idx,
2771 }
2772}
2773
2774pub mod iter {
2775 pub trait Iterator {
2776 type Item;
2777 }
2778
2779 pub trait IntoIterator {
2780 type Item;
2781 type IntoIter: Iterator<Item = Self::Item>;
2782 }
2783
2784 impl<T> IntoIterator for T where T: Iterator {
2785 type Item = <T as Iterator>::Item;
2786 type IntoIter = Self;
2787 }
2788}
2789
2790trait Step {}
2791impl Step for i32 {}
2792impl Step for i64 {}
2793
2794impl<A: Step> iter::Iterator for ops::Range<A> {
2795 type Item = A;
2796}
2797"#,
2798 );
2799 assert_eq!(t, "i32");
2800}
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index ccab246bf..88a422d2c 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -290,8 +290,7 @@ fn trait_object_unsize_impl_datum(
290 let self_trait_ref = TraitRef { trait_, substs: self_substs }; 290 let self_trait_ref = TraitRef { trait_, substs: self_substs };
291 let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)]; 291 let where_clauses = vec![GenericPredicate::Implemented(self_trait_ref)];
292 292
293 let impl_substs = 293 let impl_substs = Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.into())).build();
294 Substs::builder(2).push(self_ty).push(Ty::Dyn(target_bounds.clone().into())).build();
295 294
296 let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs }; 295 let trait_ref = TraitRef { trait_: unsize_trait, substs: impl_substs };
297 296
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index e2f2a9ccb..61de3cc30 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -4,6 +4,7 @@ use std::sync::Arc;
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; 6use chalk_ir::{fold::shift::Shift, GenericArg, TypeName};
7use chalk_solve::rust_ir::{self, WellKnownTrait};
7 8
8use hir_def::{ 9use hir_def::{
9 lang_item::{lang_attr, LangItemTarget}, 10 lang_item::{lang_attr, LangItemTarget},
@@ -14,9 +15,8 @@ use ra_db::{salsa::InternKey, CrateId};
14use super::{builtin, AssocTyValue, ChalkContext, Impl}; 15use super::{builtin, AssocTyValue, ChalkContext, Impl};
15use crate::{ 16use crate::{
16 db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics, 17 db::HirDatabase, display::HirDisplay, method_resolution::TyFingerprint, utils::generics,
17 DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor, 18 CallableDef, DebruijnIndex, GenericPredicate, Substs, Ty, TypeCtor,
18}; 19};
19use chalk_rust_ir::WellKnownTrait;
20use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders}; 20use mapping::{convert_where_clauses, generic_predicate_to_inline_bound, make_binders};
21 21
22pub use self::interner::*; 22pub use self::interner::*;
@@ -54,10 +54,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
54 54
55 fn fn_def_datum( 55 fn fn_def_datum(
56 &self, 56 &self,
57 _fn_def_id: chalk_ir::FnDefId<Interner>, 57 fn_def_id: chalk_ir::FnDefId<Interner>,
58 ) -> Arc<chalk_rust_ir::FnDefDatum<Interner>> { 58 ) -> Arc<rust_ir::FnDefDatum<Interner>> {
59 // We don't yet provide any FnDefs to Chalk 59 self.db.fn_def_datum(self.krate, fn_def_id)
60 unimplemented!()
61 } 60 }
62 61
63 fn impls_for_trait( 62 fn impls_for_trait(
@@ -113,7 +112,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
113 } 112 }
114 fn well_known_trait_id( 113 fn well_known_trait_id(
115 &self, 114 &self,
116 well_known_trait: chalk_rust_ir::WellKnownTrait, 115 well_known_trait: rust_ir::WellKnownTrait,
117 ) -> Option<chalk_ir::TraitId<Interner>> { 116 ) -> Option<chalk_ir::TraitId<Interner>> {
118 let lang_attr = lang_attr_from_well_known_trait(well_known_trait); 117 let lang_attr = lang_attr_from_well_known_trait(well_known_trait);
119 let lang_items = self.db.crate_lang_items(self.krate); 118 let lang_items = self.db.crate_lang_items(self.krate);
@@ -134,13 +133,13 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
134 fn opaque_ty_data( 133 fn opaque_ty_data(
135 &self, 134 &self,
136 _id: chalk_ir::OpaqueTyId<Interner>, 135 _id: chalk_ir::OpaqueTyId<Interner>,
137 ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> { 136 ) -> Arc<rust_ir::OpaqueTyDatum<Interner>> {
138 unimplemented!() 137 unimplemented!()
139 } 138 }
140 139
141 fn force_impl_for( 140 fn force_impl_for(
142 &self, 141 &self,
143 _well_known: chalk_rust_ir::WellKnownTrait, 142 _well_known: rust_ir::WellKnownTrait,
144 _ty: &chalk_ir::TyData<Interner>, 143 _ty: &chalk_ir::TyData<Interner>,
145 ) -> Option<bool> { 144 ) -> Option<bool> {
146 // this method is mostly for rustc 145 // this method is mostly for rustc
@@ -151,6 +150,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
151 // FIXME: implement actual object safety 150 // FIXME: implement actual object safety
152 true 151 true
153 } 152 }
153
154 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
155 Ty::Unknown.to_chalk(self.db)
156 }
154} 157}
155 158
156pub(crate) fn program_clauses_for_chalk_env_query( 159pub(crate) fn program_clauses_for_chalk_env_query(
@@ -189,7 +192,7 @@ pub(crate) fn associated_ty_data_query(
189 .collect(); 192 .collect();
190 193
191 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); 194 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
192 let bound_data = chalk_rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; 195 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
193 let datum = AssociatedTyDatum { 196 let datum = AssociatedTyDatum {
194 trait_id: trait_.to_chalk(db), 197 trait_id: trait_.to_chalk(db),
195 id, 198 id,
@@ -210,7 +213,7 @@ pub(crate) fn trait_datum_query(
210 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 213 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
211 let generic_params = generics(db.upcast(), trait_.into()); 214 let generic_params = generics(db.upcast(), trait_.into());
212 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 215 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
213 let flags = chalk_rust_ir::TraitFlags { 216 let flags = rust_ir::TraitFlags {
214 auto: trait_data.auto, 217 auto: trait_data.auto,
215 upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate, 218 upstream: trait_.lookup(db.upcast()).container.module(db.upcast()).krate != krate,
216 non_enumerable: true, 219 non_enumerable: true,
@@ -222,7 +225,7 @@ pub(crate) fn trait_datum_query(
222 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars); 225 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
223 let associated_ty_ids = 226 let associated_ty_ids =
224 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect(); 227 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect();
225 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; 228 let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
226 let well_known = 229 let well_known =
227 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); 230 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
228 let trait_datum = TraitDatum { 231 let trait_datum = TraitDatum {
@@ -272,12 +275,12 @@ pub(crate) fn struct_datum_query(
272 convert_where_clauses(db, generic_def, &bound_vars) 275 convert_where_clauses(db, generic_def, &bound_vars)
273 }) 276 })
274 .unwrap_or_else(Vec::new); 277 .unwrap_or_else(Vec::new);
275 let flags = chalk_rust_ir::AdtFlags { 278 let flags = rust_ir::AdtFlags {
276 upstream, 279 upstream,
277 // FIXME set fundamental flag correctly 280 // FIXME set fundamental flag correctly
278 fundamental: false, 281 fundamental: false,
279 }; 282 };
280 let struct_datum_bound = chalk_rust_ir::AdtDatumBound { 283 let struct_datum_bound = rust_ir::AdtDatumBound {
281 fields: Vec::new(), // FIXME add fields (only relevant for auto traits) 284 fields: Vec::new(), // FIXME add fields (only relevant for auto traits)
282 where_clauses, 285 where_clauses,
283 }; 286 };
@@ -317,9 +320,9 @@ fn impl_def_datum(
317 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 320 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
318 let trait_ = trait_ref.trait_; 321 let trait_ = trait_ref.trait_;
319 let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate { 322 let impl_type = if impl_id.lookup(db.upcast()).container.module(db.upcast()).krate == krate {
320 chalk_rust_ir::ImplType::Local 323 rust_ir::ImplType::Local
321 } else { 324 } else {
322 chalk_rust_ir::ImplType::External 325 rust_ir::ImplType::External
323 }; 326 };
324 let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars); 327 let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars);
325 let negative = impl_data.is_negative; 328 let negative = impl_data.is_negative;
@@ -332,13 +335,9 @@ fn impl_def_datum(
332 ); 335 );
333 let trait_ref = trait_ref.to_chalk(db); 336 let trait_ref = trait_ref.to_chalk(db);
334 337
335 let polarity = if negative { 338 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
336 chalk_rust_ir::Polarity::Negative
337 } else {
338 chalk_rust_ir::Polarity::Positive
339 };
340 339
341 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; 340 let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
342 let trait_data = db.trait_data(trait_); 341 let trait_data = db.trait_data(trait_);
343 let associated_ty_value_ids = impl_data 342 let associated_ty_value_ids = impl_data
344 .items 343 .items
@@ -396,8 +395,8 @@ fn type_alias_associated_ty_value(
396 .associated_type_by_name(&type_alias_data.name) 395 .associated_type_by_name(&type_alias_data.name)
397 .expect("assoc ty value should not exist"); // validated when building the impl data as well 396 .expect("assoc ty value should not exist"); // validated when building the impl data as well
398 let ty = db.ty(type_alias.into()); 397 let ty = db.ty(type_alias.into());
399 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; 398 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) };
400 let value = chalk_rust_ir::AssociatedTyValue { 399 let value = rust_ir::AssociatedTyValue {
401 impl_id: Impl::ImplDef(impl_id).to_chalk(db), 400 impl_id: Impl::ImplDef(impl_id).to_chalk(db),
402 associated_ty_id: assoc_ty.to_chalk(db), 401 associated_ty_id: assoc_ty.to_chalk(db),
403 value: make_binders(value_bound, ty.num_binders), 402 value: make_binders(value_bound, ty.num_binders),
@@ -405,6 +404,26 @@ fn type_alias_associated_ty_value(
405 Arc::new(value) 404 Arc::new(value)
406} 405}
407 406
407pub(crate) fn fn_def_datum_query(
408 db: &dyn HirDatabase,
409 _krate: CrateId,
410 fn_def_id: FnDefId,
411) -> Arc<FnDefDatum> {
412 let callable_def: CallableDef = from_chalk(db, fn_def_id);
413 let generic_params = generics(db.upcast(), callable_def.into());
414 let sig = db.callable_item_signature(callable_def);
415 let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST);
416 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
417 let bound = rust_ir::FnDefDatumBound {
418 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
419 argument_types: sig.value.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(),
420 return_type: sig.value.ret().clone().to_chalk(db),
421 where_clauses,
422 };
423 let datum = FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders) };
424 Arc::new(datum)
425}
426
408impl From<AdtId> for crate::TypeCtorId { 427impl From<AdtId> for crate::TypeCtorId {
409 fn from(struct_id: AdtId) -> Self { 428 fn from(struct_id: AdtId) -> Self {
410 struct_id.0 429 struct_id.0
@@ -417,6 +436,18 @@ impl From<crate::TypeCtorId> for AdtId {
417 } 436 }
418} 437}
419 438
439impl From<FnDefId> for crate::CallableDefId {
440 fn from(fn_def_id: FnDefId) -> Self {
441 InternKey::from_intern_id(fn_def_id.0)
442 }
443}
444
445impl From<crate::CallableDefId> for FnDefId {
446 fn from(callable_def_id: crate::CallableDefId) -> Self {
447 chalk_ir::FnDefId(callable_def_id.as_intern_id())
448 }
449}
450
420impl From<ImplId> for crate::traits::GlobalImplId { 451impl From<ImplId> for crate::traits::GlobalImplId {
421 fn from(impl_id: ImplId) -> Self { 452 fn from(impl_id: ImplId) -> Self {
422 InternKey::from_intern_id(impl_id.0) 453 InternKey::from_intern_id(impl_id.0)
@@ -429,14 +460,14 @@ impl From<crate::traits::GlobalImplId> for ImplId {
429 } 460 }
430} 461}
431 462
432impl From<chalk_rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { 463impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId {
433 fn from(id: chalk_rust_ir::AssociatedTyValueId<Interner>) -> Self { 464 fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self {
434 Self::from_intern_id(id.0) 465 Self::from_intern_id(id.0)
435 } 466 }
436} 467}
437 468
438impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId<Interner> { 469impl From<crate::traits::AssocTyValueId> for rust_ir::AssociatedTyValueId<Interner> {
439 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self { 470 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self {
440 chalk_rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id()) 471 rust_ir::AssociatedTyValueId(assoc_ty_value_id.as_intern_id())
441 } 472 }
442} 473}
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs
index 060372819..e27074ba6 100644
--- a/crates/ra_hir_ty/src/traits/chalk/interner.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs
@@ -11,15 +11,17 @@ use std::{fmt, sync::Arc};
11pub struct Interner; 11pub struct Interner;
12 12
13pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 13pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
14pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<Interner>; 14pub type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
15pub type TraitId = chalk_ir::TraitId<Interner>; 15pub type TraitId = chalk_ir::TraitId<Interner>;
16pub type TraitDatum = chalk_rust_ir::TraitDatum<Interner>; 16pub type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
17pub type AdtId = chalk_ir::AdtId<Interner>; 17pub type AdtId = chalk_ir::AdtId<Interner>;
18pub type StructDatum = chalk_rust_ir::AdtDatum<Interner>; 18pub type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
19pub type ImplId = chalk_ir::ImplId<Interner>; 19pub type ImplId = chalk_ir::ImplId<Interner>;
20pub type ImplDatum = chalk_rust_ir::ImplDatum<Interner>; 20pub type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
21pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId<Interner>; 21pub type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
22pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<Interner>; 22pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
23pub type FnDefId = chalk_ir::FnDefId<Interner>;
24pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
23 25
24impl chalk_ir::interner::Interner for Interner { 26impl chalk_ir::interner::Interner for Interner {
25 type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? 27 type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc?
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
index a83d82fd8..5f6daf842 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -7,6 +7,7 @@ use chalk_ir::{
7 cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName, 7 cast::Cast, fold::shift::Shift, interner::HasInterner, PlaceholderIndex, Scalar, TypeName,
8 UniverseIndex, 8 UniverseIndex,
9}; 9};
10use chalk_solve::rust_ir;
10 11
11use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; 12use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId};
12use ra_db::salsa::InternKey; 13use ra_db::salsa::InternKey;
@@ -15,8 +16,8 @@ use crate::{
15 db::HirDatabase, 16 db::HirDatabase,
16 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain},