aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/display.rs2
-rw-r--r--crates/hir_def/src/data.rs4
-rw-r--r--crates/hir_def/src/generics.rs20
-rw-r--r--crates/hir_def/src/intern.rs2
-rw-r--r--crates/hir_def/src/item_tree.rs4
-rw-r--r--crates/hir_def/src/item_tree/lower.rs13
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs4
-rw-r--r--crates/hir_def/src/path.rs9
-rw-r--r--crates/hir_def/src/path/lower.rs15
-rw-r--r--crates/hir_def/src/type_ref.rs14
-rw-r--r--crates/hir_ty/src/display.rs7
-rw-r--r--crates/hir_ty/src/lower.rs3
-rw-r--r--docs/user/manual.adoc10
13 files changed, 64 insertions, 43 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 508ac37c2..c5cf803fd 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -92,7 +92,7 @@ impl HirDisplay for Function {
92 &data.ret_type 92 &data.ret_type
93 } else { 93 } else {
94 match &*data.ret_type { 94 match &*data.ret_type {
95 TypeRef::ImplTrait(bounds) => match &bounds[0] { 95 TypeRef::ImplTrait(bounds) => match bounds[0].as_ref() {
96 TypeBound::Path(path) => { 96 TypeBound::Path(path) => {
97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings 97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
98 [0] 98 [0]
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 135a6698e..8bcac60ef 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -112,7 +112,7 @@ pub struct TypeAliasData {
112 pub visibility: RawVisibility, 112 pub visibility: RawVisibility,
113 pub is_extern: bool, 113 pub is_extern: bool,
114 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). 114 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
115 pub bounds: Vec<TypeBound>, 115 pub bounds: Vec<Interned<TypeBound>>,
116} 116}
117 117
118impl TypeAliasData { 118impl TypeAliasData {
@@ -141,7 +141,7 @@ pub struct TraitData {
141 pub is_auto: bool, 141 pub is_auto: bool,
142 pub is_unsafe: bool, 142 pub is_unsafe: bool,
143 pub visibility: RawVisibility, 143 pub visibility: RawVisibility,
144 pub bounds: Box<[TypeBound]>, 144 pub bounds: Box<[Interned<TypeBound>]>,
145} 145}
146 146
147impl TraitData { 147impl TraitData {
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index de5acced8..44d22b918 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -68,9 +68,19 @@ pub struct GenericParams {
68/// associated type bindings like `Iterator<Item = u32>`. 68/// associated type bindings like `Iterator<Item = u32>`.
69#[derive(Clone, PartialEq, Eq, Debug, Hash)] 69#[derive(Clone, PartialEq, Eq, Debug, Hash)]
70pub enum WherePredicate { 70pub enum WherePredicate {
71 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, 71 TypeBound {
72 Lifetime { target: LifetimeRef, bound: LifetimeRef }, 72 target: WherePredicateTypeTarget,
73 ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, 73 bound: Interned<TypeBound>,
74 },
75 Lifetime {
76 target: LifetimeRef,
77 bound: LifetimeRef,
78 },
79 ForLifetime {
80 lifetimes: Box<[Name]>,
81 target: WherePredicateTypeTarget,
82 bound: Interned<TypeBound>,
83 },
74} 84}
75 85
76#[derive(Clone, PartialEq, Eq, Debug, Hash)] 86#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -339,11 +349,11 @@ impl GenericParams {
339 Some(hrtb_lifetimes) => WherePredicate::ForLifetime { 349 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
340 lifetimes: hrtb_lifetimes.clone(), 350 lifetimes: hrtb_lifetimes.clone(),
341 target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), 351 target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
342 bound, 352 bound: Interned::new(bound),
343 }, 353 },
344 None => WherePredicate::TypeBound { 354 None => WherePredicate::TypeBound {
345 target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), 355 target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
346 bound, 356 bound: Interned::new(bound),
347 }, 357 },
348 }, 358 },
349 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { 359 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs
index 5cc7f2df6..1189c9327 100644
--- a/crates/hir_def/src/intern.rs
+++ b/crates/hir_def/src/intern.rs
@@ -216,7 +216,9 @@ pub use crate::_impl_internable as impl_internable;
216impl_internable!( 216impl_internable!(
217 crate::type_ref::TypeRef, 217 crate::type_ref::TypeRef,
218 crate::type_ref::TraitRef, 218 crate::type_ref::TraitRef,
219 crate::type_ref::TypeBound,
219 crate::path::ModPath, 220 crate::path::ModPath,
221 crate::path::GenericArgs,
220 GenericParams, 222 GenericParams,
221 str, 223 str,
222); 224);
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 4a5f44027..11767d100 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -644,7 +644,7 @@ pub struct Trait {
644 pub generic_params: Interned<GenericParams>, 644 pub generic_params: Interned<GenericParams>,
645 pub is_auto: bool, 645 pub is_auto: bool,
646 pub is_unsafe: bool, 646 pub is_unsafe: bool,
647 pub bounds: Box<[TypeBound]>, 647 pub bounds: Box<[Interned<TypeBound>]>,
648 pub items: Box<[AssocItem]>, 648 pub items: Box<[AssocItem]>,
649 pub ast_id: FileAstId<ast::Trait>, 649 pub ast_id: FileAstId<ast::Trait>,
650} 650}
@@ -664,7 +664,7 @@ pub struct TypeAlias {
664 pub name: Name, 664 pub name: Name,
665 pub visibility: RawVisibilityId, 665 pub visibility: RawVisibilityId,
666 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. 666 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
667 pub bounds: Box<[TypeBound]>, 667 pub bounds: Box<[Interned<TypeBound>]>,
668 pub generic_params: Interned<GenericParams>, 668 pub generic_params: Interned<GenericParams>,
669 pub type_ref: Option<Interned<TypeRef>>, 669 pub type_ref: Option<Interned<TypeRef>>,
670 pub is_extern: bool, 670 pub is_extern: bool,
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 91cf75371..b4389371f 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -384,7 +384,7 @@ impl<'a> Ctx<'a> {
384 384
385 let ret_type = if func.async_token().is_some() { 385 let ret_type = if func.async_token().is_some() {
386 let future_impl = desugar_future_path(ret_type); 386 let future_impl = desugar_future_path(ret_type);
387 let ty_bound = TypeBound::Path(future_impl); 387 let ty_bound = Interned::new(TypeBound::Path(future_impl));
388 TypeRef::ImplTrait(vec![ty_bound]) 388 TypeRef::ImplTrait(vec![ty_bound])
389 } else { 389 } else {
390 ret_type 390 ret_type
@@ -738,11 +738,12 @@ impl<'a> Ctx<'a> {
738 Interned::new(generics) 738 Interned::new(generics)
739 } 739 }
740 740
741 fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { 741 fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<Interned<TypeBound>> {
742 match node.type_bound_list() { 742 match node.type_bound_list() {
743 Some(bound_list) => { 743 Some(bound_list) => bound_list
744 bound_list.bounds().map(|it| TypeBound::from_ast(&self.body_ctx, it)).collect() 744 .bounds()
745 } 745 .map(|it| Interned::new(TypeBound::from_ast(&self.body_ctx, it)))
746 .collect(),
746 None => Vec::new(), 747 None => Vec::new(),
747 } 748 }
748 } 749 }
@@ -810,7 +811,7 @@ fn desugar_future_path(orig: TypeRef) -> Path {
810 let binding = 811 let binding =
811 AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() }; 812 AssociatedTypeBinding { name: name![Output], type_ref: Some(orig), bounds: Vec::new() };
812 last.bindings.push(binding); 813 last.bindings.push(binding);
813 generic_args.push(Some(Arc::new(last))); 814 generic_args.push(Some(Interned::new(last)));
814 815
815 Path::from_known_path(path, generic_args) 816 Path::from_known_path(path, generic_args)
816} 817}
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index 4bc87a0e2..9394a5de6 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -513,13 +513,13 @@ impl<'a> Printer<'a> {
513 } 513 }
514 } 514 }
515 515
516 fn print_type_bounds(&mut self, bounds: &[TypeBound]) { 516 fn print_type_bounds(&mut self, bounds: &[Interned<TypeBound>]) {
517 for (i, bound) in bounds.iter().enumerate() { 517 for (i, bound) in bounds.iter().enumerate() {
518 if i != 0 { 518 if i != 0 {
519 w!(self, " + "); 519 w!(self, " + ");
520 } 520 }
521 521
522 match bound { 522 match bound.as_ref() {
523 TypeBound::Path(path) => self.print_path(path), 523 TypeBound::Path(path) => self.print_path(path),
524 TypeBound::Lifetime(lt) => w!(self, "{}", lt.name), 524 TypeBound::Lifetime(lt) => w!(self, "{}", lt.name),
525 TypeBound::Error => w!(self, "{{unknown}}"), 525 TypeBound::Error => w!(self, "{{unknown}}"),
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 9b8873fd2..45ab9d0ff 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -4,7 +4,6 @@ mod lower;
4use std::{ 4use std::{
5 fmt::{self, Display}, 5 fmt::{self, Display},
6 iter, 6 iter,
7 sync::Arc,
8}; 7};
9 8
10use crate::{body::LowerCtx, db::DefDatabase, intern::Interned, type_ref::LifetimeRef}; 9use crate::{body::LowerCtx, db::DefDatabase, intern::Interned, type_ref::LifetimeRef};
@@ -136,7 +135,7 @@ pub struct Path {
136 type_anchor: Option<Interned<TypeRef>>, 135 type_anchor: Option<Interned<TypeRef>>,
137 mod_path: Interned<ModPath>, 136 mod_path: Interned<ModPath>,
138 /// Invariant: the same len as `self.mod_path.segments` 137 /// Invariant: the same len as `self.mod_path.segments`
139 generic_args: Vec<Option<Arc<GenericArgs>>>, 138 generic_args: Vec<Option<Interned<GenericArgs>>>,
140} 139}
141 140
142/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This 141/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
@@ -165,7 +164,7 @@ pub struct AssociatedTypeBinding {
165 /// Bounds for the associated type, like in `Iterator<Item: 164 /// Bounds for the associated type, like in `Iterator<Item:
166 /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds` 165 /// SomeOtherTrait>`. (This is the unstable `associated_type_bounds`
167 /// feature.) 166 /// feature.)
168 pub bounds: Vec<TypeBound>, 167 pub bounds: Vec<Interned<TypeBound>>,
169} 168}
170 169
171/// A single generic argument. 170/// A single generic argument.
@@ -185,7 +184,7 @@ impl Path {
185 /// Converts a known mod path to `Path`. 184 /// Converts a known mod path to `Path`.
186 pub(crate) fn from_known_path( 185 pub(crate) fn from_known_path(
187 path: ModPath, 186 path: ModPath,
188 generic_args: Vec<Option<Arc<GenericArgs>>>, 187 generic_args: Vec<Option<Interned<GenericArgs>>>,
189 ) -> Path { 188 ) -> Path {
190 Path { type_anchor: None, mod_path: Interned::new(path), generic_args } 189 Path { type_anchor: None, mod_path: Interned::new(path), generic_args }
191 } 190 }
@@ -239,7 +238,7 @@ pub struct PathSegment<'a> {
239 238
240pub struct PathSegments<'a> { 239pub struct PathSegments<'a> {
241 segments: &'a [Name], 240 segments: &'a [Name],
242 generic_args: &'a [Option<Arc<GenericArgs>>], 241 generic_args: &'a [Option<Interned<GenericArgs>>],
243} 242}
244 243
245impl<'a> PathSegments<'a> { 244impl<'a> PathSegments<'a> {
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index a873325b2..5d5dd9c8f 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -3,7 +3,6 @@
3mod lower_use; 3mod lower_use;
4 4
5use crate::intern::Interned; 5use crate::intern::Interned;
6use std::sync::Arc;
7 6
8use either::Either; 7use either::Either;
9use hir_expand::name::{name, AsName}; 8use hir_expand::name::{name, AsName};
@@ -48,7 +47,7 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
48 segment.ret_type(), 47 segment.ret_type(),
49 ) 48 )
50 }) 49 })
51 .map(Arc::new); 50 .map(Interned::new);
52 segments.push(name); 51 segments.push(name);
53 generic_args.push(args) 52 generic_args.push(args)
54 } 53 }
@@ -87,13 +86,13 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
87 // Insert the type reference (T in the above example) as Self parameter for the trait 86 // Insert the type reference (T in the above example) as Self parameter for the trait
88 let last_segment = 87 let last_segment =
89 generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?; 88 generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?;
90 if last_segment.is_none() { 89 let mut args_inner = match last_segment {
91 *last_segment = Some(Arc::new(GenericArgs::empty())); 90 Some(it) => it.as_ref().clone(),
91 None => GenericArgs::empty(),
92 }; 92 };
93 let args = last_segment.as_mut().unwrap();
94 let mut args_inner = Arc::make_mut(args);
95 args_inner.has_self_type = true; 93 args_inner.has_self_type = true;
96 args_inner.args.insert(0, GenericArg::Type(self_type)); 94 args_inner.args.insert(0, GenericArg::Type(self_type));
95 *last_segment = Some(Interned::new(args_inner));
97 } 96 }
98 } 97 }
99 } 98 }
@@ -171,7 +170,9 @@ pub(super) fn lower_generic_args(
171 let name = name_ref.as_name(); 170 let name = name_ref.as_name();
172 let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it)); 171 let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
173 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { 172 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
174 l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() 173 l.bounds()
174 .map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))
175 .collect()
175 } else { 176 } else {
176 Vec::new() 177 Vec::new()
177 }; 178 };
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs
index cdcab7110..cbde6b940 100644
--- a/crates/hir_def/src/type_ref.rs
+++ b/crates/hir_def/src/type_ref.rs
@@ -5,7 +5,7 @@ use hir_expand::{name::Name, AstId, InFile};
5use std::convert::TryInto; 5use std::convert::TryInto;
6use syntax::ast; 6use syntax::ast;
7 7
8use crate::{body::LowerCtx, path::Path}; 8use crate::{body::LowerCtx, intern::Interned, path::Path};
9 9
10#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 10#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
11pub enum Mutability { 11pub enum Mutability {
@@ -91,8 +91,8 @@ pub enum TypeRef {
91 /// A fn pointer. Last element of the vector is the return type. 91 /// A fn pointer. Last element of the vector is the return type.
92 Fn(Vec<TypeRef>, bool /*varargs*/), 92 Fn(Vec<TypeRef>, bool /*varargs*/),
93 // For 93 // For
94 ImplTrait(Vec<TypeBound>), 94 ImplTrait(Vec<Interned<TypeBound>>),
95 DynTrait(Vec<TypeBound>), 95 DynTrait(Vec<Interned<TypeBound>>),
96 Macro(AstId<ast::MacroCall>), 96 Macro(AstId<ast::MacroCall>),
97 Error, 97 Error,
98} 98}
@@ -232,7 +232,7 @@ impl TypeRef {
232 | TypeRef::Slice(type_ref) => go(&type_ref, f), 232 | TypeRef::Slice(type_ref) => go(&type_ref, f),
233 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { 233 TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
234 for bound in bounds { 234 for bound in bounds {
235 match bound { 235 match bound.as_ref() {
236 TypeBound::Path(path) => go_path(path, f), 236 TypeBound::Path(path) => go_path(path, f),
237 TypeBound::Lifetime(_) | TypeBound::Error => (), 237 TypeBound::Lifetime(_) | TypeBound::Error => (),
238 } 238 }
@@ -262,7 +262,7 @@ impl TypeRef {
262 go(type_ref, f); 262 go(type_ref, f);
263 } 263 }
264 for bound in &binding.bounds { 264 for bound in &binding.bounds {
265 match bound { 265 match bound.as_ref() {
266 TypeBound::Path(path) => go_path(path, f), 266 TypeBound::Path(path) => go_path(path, f),
267 TypeBound::Lifetime(_) | TypeBound::Error => (), 267 TypeBound::Lifetime(_) | TypeBound::Error => (),
268 } 268 }
@@ -277,9 +277,9 @@ impl TypeRef {
277pub(crate) fn type_bounds_from_ast( 277pub(crate) fn type_bounds_from_ast(
278 lower_ctx: &LowerCtx, 278 lower_ctx: &LowerCtx,
279 type_bounds_opt: Option<ast::TypeBoundList>, 279 type_bounds_opt: Option<ast::TypeBoundList>,
280) -> Vec<TypeBound> { 280) -> Vec<Interned<TypeBound>> {
281 if let Some(type_bounds) = type_bounds_opt { 281 if let Some(type_bounds) = type_bounds_opt {
282 type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() 282 type_bounds.bounds().map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it))).collect()
283 } else { 283 } else {
284 vec![] 284 vec![]
285 } 285 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 7bbd1a1f7..637bbc634 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -13,6 +13,7 @@ use hir_def::{
13 db::DefDatabase, 13 db::DefDatabase,
14 find_path, 14 find_path,
15 generics::TypeParamProvenance, 15 generics::TypeParamProvenance,
16 intern::{Internable, Interned},
16 item_scope::ItemInNs, 17 item_scope::ItemInNs,
17 path::{Path, PathKind}, 18 path::{Path, PathKind},
18 type_ref::{TypeBound, TypeRef}, 19 type_ref::{TypeBound, TypeRef},
@@ -256,6 +257,12 @@ impl<T: HirDisplay> HirDisplay for &'_ T {
256 } 257 }
257} 258}
258 259
260impl<T: HirDisplay + Internable> HirDisplay for Interned<T> {
261 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
262 HirDisplay::hir_fmt(self.as_ref(), f)
263 }
264}
265
259impl HirDisplay for ProjectionTy { 266impl HirDisplay for ProjectionTy {
260 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 267 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
261 if f.should_truncate() { 268 if f.should_truncate() {
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 8a375b973..1645ac533 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -10,6 +10,7 @@ use std::{iter, sync::Arc};
10 10
11use base_db::CrateId; 11use base_db::CrateId;
12use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; 12use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
13use hir_def::intern::Interned;
13use hir_def::{ 14use hir_def::{
14 adt::StructKind, 15 adt::StructKind,
15 body::{Expander, LowerCtx}, 16 body::{Expander, LowerCtx},
@@ -843,7 +844,7 @@ impl<'a> TyLoweringContext<'a> {
843 }) 844 })
844 } 845 }
845 846
846 fn lower_impl_trait(&self, bounds: &[TypeBound]) -> ReturnTypeImplTrait { 847 fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>]) -> ReturnTypeImplTrait {
847 cov_mark::hit!(lower_rpit); 848 cov_mark::hit!(lower_rpit);
848 let self_ty = 849 let self_ty =
849 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); 850 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index ad367511b..1f95df56e 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -139,18 +139,18 @@ $ cargo xtask install --server
139=== rust-analyzer Language Server Binary 139=== rust-analyzer Language Server Binary
140 140
141Other editors generally require the `rust-analyzer` binary to be in `$PATH`. 141Other editors generally require the `rust-analyzer` binary to be in `$PATH`.
142You can download the pre-built binary from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page. 142You can download pre-built binaries from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page.
143Typically, you then need to rename the binary for your platform, e.g. `rust-analyzer-mac` if you're on Mac OS, to `rust-analyzer` and make it executable in addition to moving it into a directory in your `$PATH`. 143You will need to uncompress and rename the binary for your platform, e.g. from `rust-analyzer-aarch64-apple-darwin.gz` on Mac OS to `rust-analyzer`, make it executable, then move it into a directory in your `$PATH`.
144 144
145On Linux to install the `rust-analyzer` binary into `~/.local/bin`, this commands could be used 145On Linux to install the `rust-analyzer` binary into `~/.local/bin`, these commands should work:
146 146
147[source,bash] 147[source,bash]
148---- 148----
149$ curl -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/rust-analyzer-linux -o ~/.local/bin/rust-analyzer 149$ curl -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz | gunzip -c - > ~/.local/bin/rust-analyzer
150$ chmod +x ~/.local/bin/rust-analyzer 150$ chmod +x ~/.local/bin/rust-analyzer
151---- 151----
152 152
153Ensure `~/.local/bin` is listed in the `$PATH` variable. 153Make sure that `~/.local/bin` is listed in the `$PATH` variable and use the appropriate URL if you're not on a `x86-64` system.
154 154
155Alternatively, you can install it from source using the command below. 155Alternatively, you can install it from source using the command below.
156You'll need the latest stable version of the Rust toolchain. 156You'll need the latest stable version of the Rust toolchain.