aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-03-25 21:00:16 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-03-25 21:00:16 +0000
commitdc94f3612583c5e960b334761ad0c18d328840ea (patch)
treec79204bca4912574614eafff8f9e18775d5aa963 /crates
parentbb77bc5c2f6c6b9681d9b3d0a068791db7eec0e2 (diff)
parent99711c1863fc712dc14ca61809055b283415acbe (diff)
Merge #1040
1040: Trait beginnings r=matklad a=flodiebold This adds some very simple trait method resolution, going through traits in scope, looking for methods of the given name, and checking very naively whether there's an impl for the given type and trait. Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model_api.rs13
-rw-r--r--crates/ra_hir/src/db.rs7
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/nameres.rs8
-rw-r--r--crates/ra_hir/src/resolve.rs17
-rw-r--r--crates/ra_hir/src/traits.rs52
-rw-r--r--crates/ra_hir/src/ty.rs23
-rw-r--r--crates/ra_hir/src/ty/infer.rs3
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs95
-rw-r--r--crates/ra_hir/src/ty/tests.rs12
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron5
12 files changed, 208 insertions, 34 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 5437133b8..88c13566c 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -17,6 +17,7 @@ use crate::{
17 impl_block::ImplBlock, 17 impl_block::ImplBlock,
18 resolve::Resolver, 18 resolve::Resolver,
19 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
20 traits::{TraitItem, TraitData},
20}; 21};
21 22
22/// hir::Crate describes a single crate. It's the main interface with which 23/// hir::Crate describes a single crate. It's the main interface with which
@@ -649,6 +650,18 @@ impl Trait {
649 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { 650 pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> {
650 db.generic_params((*self).into()) 651 db.generic_params((*self).into())
651 } 652 }
653
654 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
655 self.trait_data(db).name().clone()
656 }
657
658 pub fn items(self, db: &impl DefDatabase) -> Vec<TraitItem> {
659 self.trait_data(db).items().to_vec()
660 }
661
662 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
663 db.trait_data(self)
664 }
652} 665}
653 666
654impl Docs for Trait { 667impl Docs for Trait {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d3908f8ac..143919cdc 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -14,6 +14,7 @@ use crate::{
14 impl_block::{ModuleImplBlocks, ImplSourceMap}, 14 impl_block::{ModuleImplBlocks, ImplSourceMap},
15 generics::{GenericParams, GenericDef}, 15 generics::{GenericParams, GenericDef},
16 type_ref::TypeRef, 16 type_ref::TypeRef,
17 traits::TraitData, Trait, ty::TraitRef
17}; 18};
18 19
19#[salsa::query_group(DefDatabaseStorage)] 20#[salsa::query_group(DefDatabaseStorage)]
@@ -27,6 +28,9 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
27 #[salsa::invoke(crate::adt::EnumData::enum_data_query)] 28 #[salsa::invoke(crate::adt::EnumData::enum_data_query)]
28 fn enum_data(&self, e: Enum) -> Arc<EnumData>; 29 fn enum_data(&self, e: Enum) -> Arc<EnumData>;
29 30
31 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
32 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
33
30 #[salsa::invoke(crate::ids::SourceFileItems::file_items_query)] 34 #[salsa::invoke(crate::ids::SourceFileItems::file_items_query)]
31 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; 35 fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
32 36
@@ -98,6 +102,9 @@ pub trait HirDatabase: DefDatabase {
98 102
99 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 103 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
100 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 104 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
105
106 #[salsa::invoke(crate::ty::method_resolution::implements)]
107 fn implements(&self, trait_ref: TraitRef) -> bool;
101} 108}
102 109
103#[test] 110#[test]
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index ce54d7608..974ebd831 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -27,6 +27,7 @@ mod ids;
27mod name; 27mod name;
28mod nameres; 28mod nameres;
29mod adt; 29mod adt;
30mod traits;
30mod type_alias; 31mod type_alias;
31mod type_ref; 32mod type_ref;
32mod ty; 33mod ty;
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 56ed872d5..c34aa4b50 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -62,7 +62,7 @@ use test_utils::tested_by;
62 62
63use crate::{ 63use crate::{
64 ModuleDef, Name, Crate, Module, 64 ModuleDef, Name, Crate, Module,
65 DefDatabase, Path, PathKind, HirFileId, 65 DefDatabase, Path, PathKind, HirFileId, Trait,
66 ids::{SourceItemId, SourceFileItemId, MacroCallId}, 66 ids::{SourceItemId, SourceFileItemId, MacroCallId},
67 diagnostics::DiagnosticSink, 67 diagnostics::DiagnosticSink,
68 nameres::diagnostics::DefDiagnostic, 68 nameres::diagnostics::DefDiagnostic,
@@ -139,6 +139,12 @@ impl ModuleScope {
139 pub fn get(&self, name: &Name) -> Option<&Resolution> { 139 pub fn get(&self, name: &Name) -> Option<&Resolution> {
140 self.items.get(name) 140 self.items.get(name)
141 } 141 }
142 pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
143 self.items.values().filter_map(|r| match r.def.take_types() {
144 Some(ModuleDef::Trait(t)) => Some(t),
145 _ => None,
146 })
147 }
142} 148}
143 149
144#[derive(Debug, Clone, PartialEq, Eq, Default)] 150#[derive(Debug, Clone, PartialEq, Eq, Default)]
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index f28154517..2609585b1 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -11,7 +11,7 @@ use crate::{
11 generics::GenericParams, 11 generics::GenericParams,
12 expr::{scope::{ExprScopes, ScopeId}, PatId, Body}, 12 expr::{scope::{ExprScopes, ScopeId}, PatId, Body},
13 impl_block::ImplBlock, 13 impl_block::ImplBlock,
14 path::Path, 14 path::Path, Trait
15}; 15};
16 16
17#[derive(Debug, Clone, Default)] 17#[derive(Debug, Clone, Default)]
@@ -175,6 +175,21 @@ impl Resolver {
175 names 175 names
176 } 176 }
177 177
178 pub(crate) fn traits_in_scope<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
179 // FIXME prelude
180 self.scopes
181 .iter()
182 .rev()
183 .flat_map(|scope| {
184 match scope {
185 Scope::ModuleScope(m) => Some(m.crate_def_map[m.module_id].scope.traits()),
186 _ => None,
187 }
188 .into_iter()
189 })
190 .flatten()
191 }
192
178 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { 193 fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> {
179 self.scopes.iter().rev().find_map(|scope| match scope { 194 self.scopes.iter().rev().find_map(|scope| match scope {
180 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 195 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
new file mode 100644
index 000000000..725bdd5cb
--- /dev/null
+++ b/crates/ra_hir/src/traits.rs
@@ -0,0 +1,52 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use ra_syntax::ast::{self, NameOwner};
6
7use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct TraitData {
11 name: Option<Name>,
12 items: Vec<TraitItem>,
13}
14
15impl TraitData {
16 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: Trait) -> Arc<TraitData> {
17 let (file_id, node) = tr.source(db);
18 let name = node.name().map(|n| n.as_name());
19 let module = tr.module(db);
20 let ctx = LocationCtx::new(db, module, file_id);
21 let items = if let Some(item_list) = node.item_list() {
22 item_list
23 .impl_items()
24 .map(|item_node| match item_node.kind() {
25 ast::ImplItemKind::FnDef(it) => Function { id: ctx.to_def(it) }.into(),
26 ast::ImplItemKind::ConstDef(it) => Const { id: ctx.to_def(it) }.into(),
27 ast::ImplItemKind::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(it) }.into(),
28 })
29 .collect()
30 } else {
31 Vec::new()
32 };
33 Arc::new(TraitData { name, items })
34 }
35
36 pub(crate) fn name(&self) -> &Option<Name> {
37 &self.name
38 }
39
40 pub(crate) fn items(&self) -> &[TraitItem] {
41 &self.items
42 }
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46pub enum TraitItem {
47 Function(Function),
48 Const(Const),
49 TypeAlias(TypeAlias),
50 // Existential
51}
52impl_froms!(TraitItem: Function, Const, TypeAlias);
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 7d25ade47..d42c61e9d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -14,7 +14,7 @@ pub(crate) mod display;
14use std::sync::Arc; 14use std::sync::Arc;
15use std::{fmt, mem}; 15use std::{fmt, mem};
16 16
17use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase}; 17use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait};
18 18
19pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig}; 19pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig};
20pub(crate) use infer::{infer, InferenceResult, InferTy}; 20pub(crate) use infer::{infer, InferenceResult, InferTy};
@@ -91,7 +91,7 @@ pub enum TypeCtor {
91/// A nominal type with (maybe 0) type parameters. This might be a primitive 91/// A nominal type with (maybe 0) type parameters. This might be a primitive
92/// type like `bool`, a struct, tuple, function pointer, reference or 92/// type like `bool`, a struct, tuple, function pointer, reference or
93/// several other things. 93/// several other things.
94#[derive(Clone, PartialEq, Eq, Debug)] 94#[derive(Clone, PartialEq, Eq, Debug, Hash)]
95pub struct ApplicationTy { 95pub struct ApplicationTy {
96 pub ctor: TypeCtor, 96 pub ctor: TypeCtor,
97 pub parameters: Substs, 97 pub parameters: Substs,
@@ -103,7 +103,7 @@ pub struct ApplicationTy {
103/// the same thing (but in a different way). 103/// the same thing (but in a different way).
104/// 104///
105/// This should be cheap to clone. 105/// This should be cheap to clone.
106#[derive(Clone, PartialEq, Eq, Debug)] 106#[derive(Clone, PartialEq, Eq, Debug, Hash)]
107pub enum Ty { 107pub enum Ty {
108 /// A nominal type with (maybe 0) type parameters. This might be a primitive 108 /// A nominal type with (maybe 0) type parameters. This might be a primitive
109 /// type like `bool`, a struct, tuple, function pointer, reference or 109 /// type like `bool`, a struct, tuple, function pointer, reference or
@@ -132,7 +132,7 @@ pub enum Ty {
132} 132}
133 133
134/// A list of substitutions for generic parameters. 134/// A list of substitutions for generic parameters.
135#[derive(Clone, PartialEq, Eq, Debug)] 135#[derive(Clone, PartialEq, Eq, Debug, Hash)]
136pub struct Substs(Arc<[Ty]>); 136pub struct Substs(Arc<[Ty]>);
137 137
138impl Substs { 138impl Substs {
@@ -169,6 +169,21 @@ impl Substs {
169 } 169 }
170} 170}
171 171
172/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
173/// Name to be bikeshedded: TraitBound? TraitImplements?
174#[derive(Clone, PartialEq, Eq, Debug, Hash)]
175pub struct TraitRef {
176 /// FIXME name?
177 trait_: Trait,
178 substs: Substs,
179}
180
181impl TraitRef {
182 pub fn self_ty(&self) -> &Ty {
183 &self.substs.0[0]
184 }
185}
186
172/// A function signature as seen by type inference: Several parameter types and 187/// A function signature as seen by type inference: Several parameter types and
173/// one return type. 188/// one return type.
174#[derive(Clone, PartialEq, Eq, Debug)] 189#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 5fd602a9e..573115321 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -821,7 +821,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
821 } 821 }
822 Expr::MethodCall { receiver, args, method_name, generic_args } => { 822 Expr::MethodCall { receiver, args, method_name, generic_args } => {
823 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 823 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
824 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 824 let resolved =
825 receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver);
825 let (derefed_receiver_ty, method_ty, def_generics) = match resolved { 826 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
826 Some((ty, func)) => { 827 Some((ty, func)) => {
827 self.write_method_resolution(tgt_expr, func); 828 self.write_method_resolution(tgt_expr, func);
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index b1684acf9..3ac8dc46b 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -8,12 +8,12 @@ use rustc_hash::FxHashMap;
8 8
9use crate::{ 9use crate::{
10 HirDatabase, Module, Crate, Name, Function, Trait, 10 HirDatabase, Module, Crate, Name, Function, Trait,
11 ids::TraitId,
12 impl_block::{ImplId, ImplBlock, ImplItem}, 11 impl_block::{ImplId, ImplBlock, ImplItem},
13 ty::{Ty, TypeCtor}, 12 ty::{Ty, TypeCtor},
14 nameres::CrateModuleId, 13 nameres::CrateModuleId, resolve::Resolver, traits::TraitItem
15 14
16}; 15};
16use super::{ TraitRef, Substs};
17 17
18/// This is used as a key for indexing impls. 18/// This is used as a key for indexing impls.
19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 19#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -38,7 +38,7 @@ pub struct CrateImplBlocks {
38 /// To make sense of the CrateModuleIds, we need the source root. 38 /// To make sense of the CrateModuleIds, we need the source root.
39 krate: Crate, 39 krate: Crate,
40 impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>, 40 impls: FxHashMap<TyFingerprint, Vec<(CrateModuleId, ImplId)>>,
41 impls_by_trait: FxHashMap<TraitId, Vec<(CrateModuleId, ImplId)>>, 41 impls_by_trait: FxHashMap<Trait, Vec<(CrateModuleId, ImplId)>>,
42} 42}
43 43
44impl CrateImplBlocks { 44impl CrateImplBlocks {
@@ -56,8 +56,7 @@ impl CrateImplBlocks {
56 &'a self, 56 &'a self,
57 tr: &Trait, 57 tr: &Trait,
58 ) -> impl Iterator<Item = ImplBlock> + 'a { 58 ) -> impl Iterator<Item = ImplBlock> + 'a {
59 let id = tr.id; 59 self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map(
60 self.impls_by_trait.get(&id).into_iter().flat_map(|i| i.iter()).map(
61 move |(module_id, impl_id)| { 60 move |(module_id, impl_id)| {
62 let module = Module { krate: self.krate, module_id: *module_id }; 61 let module = Module { krate: self.krate, module_id: *module_id };
63 ImplBlock::from_id(module, *impl_id) 62 ImplBlock::from_id(module, *impl_id)
@@ -73,18 +72,18 @@ impl CrateImplBlocks {
73 72
74 let target_ty = impl_block.target_ty(db); 73 let target_ty = impl_block.target_ty(db);
75 74
76 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
77 self.impls
78 .entry(target_ty_fp)
79 .or_insert_with(Vec::new)
80 .push((module.module_id, impl_id));
81 }
82
83 if let Some(tr) = impl_block.target_trait(db) { 75 if let Some(tr) = impl_block.target_trait(db) {
84 self.impls_by_trait 76 self.impls_by_trait
85 .entry(tr.id) 77 .entry(tr)
86 .or_insert_with(Vec::new) 78 .or_insert_with(Vec::new)
87 .push((module.module_id, impl_id)); 79 .push((module.module_id, impl_id));
80 } else {
81 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
82 self.impls
83 .entry(target_ty_fp)
84 .or_insert_with(Vec::new)
85 .push((module.module_id, impl_id));
86 }
88 } 87 }
89 } 88 }
90 89
@@ -109,6 +108,20 @@ impl CrateImplBlocks {
109 } 108 }
110} 109}
111 110
111/// Rudimentary check whether an impl exists for a given type and trait; this
112/// will actually be done by chalk.
113pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> bool {
114 // FIXME use all trait impls in the whole crate graph
115 let krate = trait_ref.trait_.module(db).krate(db);
116 let krate = match krate {
117 Some(krate) => krate,
118 None => return false,
119 };
120 let crate_impl_blocks = db.impls_in_crate(krate);
121 let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_);
122 impl_blocks.any(|impl_block| &impl_block.target_ty(db) == trait_ref.self_ty())
123}
124
112fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { 125fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
113 match ty { 126 match ty {
114 Ty::Apply(a_ty) => match a_ty.ctor { 127 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -120,20 +133,64 @@ fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
120} 133}
121 134
122impl Ty { 135impl Ty {
123 // FIXME: cache this as a query?
124 // - if so, what signature? (TyFingerprint, Name)?
125 // - or maybe cache all names and def_ids of methods per fingerprint?
126 /// Look up the method with the given name, returning the actual autoderefed 136 /// Look up the method with the given name, returning the actual autoderefed
127 /// receiver type (but without autoref applied yet). 137 /// receiver type (but without autoref applied yet).
128 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<(Ty, Function)> { 138 pub fn lookup_method(
129 self.iterate_methods(db, |ty, f| { 139 self,
140 db: &impl HirDatabase,
141 name: &Name,
142 resolver: &Resolver,
143 ) -> Option<(Ty, Function)> {
144 // FIXME: trait methods should be used before autoderefs
145 let inherent_method = self.clone().iterate_methods(db, |ty, f| {
130 let sig = f.signature(db); 146 let sig = f.signature(db);
131 if sig.name() == name && sig.has_self_param() { 147 if sig.name() == name && sig.has_self_param() {
132 Some((ty.clone(), f)) 148 Some((ty.clone(), f))
133 } else { 149 } else {
134 None 150 None
135 } 151 }
136 }) 152 });
153 inherent_method.or_else(|| self.lookup_trait_method(db, name, resolver))
154 }
155
156 fn lookup_trait_method(
157 self,
158 db: &impl HirDatabase,
159 name: &Name,
160 resolver: &Resolver,
161 ) -> Option<(Ty, Function)> {
162 let mut candidates = Vec::new();
163 for t in resolver.traits_in_scope() {
164 let data = t.trait_data(db);
165 for item in data.items() {
166 match item {
167 &TraitItem::Function(m) => {
168 let sig = m.signature(db);
169 if sig.name() == name && sig.has_self_param() {
170 candidates.push((t, m));
171 }
172 }
173 _ => {}
174 }
175 }
176 }
177 // FIXME:
178 // - we might not actually be able to determine fully that the type
179 // implements the trait here; it's enough if we (well, Chalk) determine
180 // that it's possible.
181 // - when the trait method is picked, we need to register an
182 // 'obligation' somewhere so that we later check that it's really
183 // implemented
184 // - both points go for additional requirements from where clauses as
185 // well (in fact, the 'implements' condition could just be considered a
186 // 'where Self: Trait' clause)
187 candidates.retain(|(t, _m)| {
188 let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) };
189 db.implements(trait_ref)
190 });
191 // FIXME if there's multiple candidates here, that's an ambiguity error
192 let (_chosen_trait, chosen_method) = candidates.first()?;
193 Some((self.clone(), *chosen_method))
137 } 194 }
138 195
139 // This would be nicer if it just returned an iterator, but that runs into 196 // This would be nicer if it just returned an iterator, but that runs into
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 3aedba243..655f3c522 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1272,8 +1272,8 @@ fn test() {
1272[241; 252) 'Struct::FOO': u32 1272[241; 252) 'Struct::FOO': u32
1273[262; 263) 'y': u32 1273[262; 263) 'y': u32
1274[266; 275) 'Enum::BAR': u32 1274[266; 275) 'Enum::BAR': u32
1275[285; 286) 'z': u32 1275[285; 286) 'z': {unknown}
1276[289; 302) 'TraitTest::ID': u32"### 1276[289; 302) 'TraitTest::ID': {unknown}"###
1277 ); 1277 );
1278} 1278}
1279 1279
@@ -1918,9 +1918,9 @@ fn test() {
1918[110; 114) 'self': &{unknown} 1918[110; 114) 'self': &{unknown}
1919[170; 228) '{ ...i128 }': () 1919[170; 228) '{ ...i128 }': ()
1920[176; 178) 'S1': S1 1920[176; 178) 'S1': S1
1921[176; 187) 'S1.method()': {unknown} 1921[176; 187) 'S1.method()': u32
1922[203; 205) 'S2': S2 1922[203; 205) 'S2': S2
1923[203; 214) 'S2.method()': {unknown}"### 1923[203; 214) 'S2.method()': i128"###
1924 ); 1924 );
1925} 1925}
1926 1926
@@ -1964,10 +1964,10 @@ mod bar_test {
1964[169; 173) 'self': &{unknown} 1964[169; 173) 'self': &{unknown}
1965[300; 337) '{ ... }': () 1965[300; 337) '{ ... }': ()
1966[310; 311) 'S': S 1966[310; 311) 'S': S
1967[310; 320) 'S.method()': {unknown} 1967[310; 320) 'S.method()': u32
1968[416; 454) '{ ... }': () 1968[416; 454) '{ ... }': ()
1969[426; 427) 'S': S 1969[426; 427) 'S': S
1970[426; 436) 'S.method()': {unknown}"### 1970[426; 436) 'S.method()': i128"###
1971 ); 1971 );
1972} 1972}
1973 1973
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 54b72f8c5..47a37e4d1 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -4061,7 +4061,11 @@ impl ast::NameOwner for TraitDef {}
4061impl ast::AttrsOwner for TraitDef {} 4061impl ast::AttrsOwner for TraitDef {}
4062impl ast::DocCommentsOwner for TraitDef {} 4062impl ast::DocCommentsOwner for TraitDef {}
4063impl ast::TypeParamsOwner for TraitDef {} 4063impl ast::TypeParamsOwner for TraitDef {}
4064impl TraitDef {} 4064impl TraitDef {
4065 pub fn item_list(&self) -> Option<&ItemList> {
4066 super::child_opt(self)
4067 }
4068}
4065 4069
4066// TrueKw 4070// TrueKw
4067#[derive(Debug, PartialEq, Eq, Hash)] 4071#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 4f8e19bd0..ad6d74162 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -292,7 +292,10 @@ Grammar(
292 ], options: [["variant_list", "EnumVariantList"]] ), 292 ], options: [["variant_list", "EnumVariantList"]] ),
293 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), 293 "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ),
294 "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner", "AttrsOwner"], options: ["Expr"] ), 294 "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner", "AttrsOwner"], options: ["Expr"] ),
295 "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner"] ), 295 "TraitDef": (
296 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner"],
297 options: ["ItemList"]
298 ),
296 "Module": ( 299 "Module": (
297 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ], 300 traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ],
298 options: [ "ItemList" ] 301 options: [ "ItemList" ]