@@ -21,6 +21,7 @@ use crate::{
2121 db:: DefDatabase ,
2222 dyn_map:: { keys, DynMap } ,
2323 expander:: Expander ,
24+ item_tree:: { AttrOwner , ItemTree } ,
2425 lower:: LowerCtx ,
2526 nameres:: { DefMap , MacroSubNs } ,
2627 src:: { HasChildSource , HasSource } ,
@@ -154,12 +155,58 @@ impl GenericParams {
154155 def : GenericDefId ,
155156 ) -> Interned < GenericParams > {
156157 let _p = profile:: span ( "generic_params_query" ) ;
158+
159+ let krate = def. module ( db) . krate ;
160+ let cfg_options = db. crate_graph ( ) ;
161+ let cfg_options = & cfg_options[ krate] . cfg_options ;
162+
163+ // Returns the generic parameters that are enabled under the current `#[cfg]` options
164+ let enabled_params = |params : & Interned < GenericParams > , item_tree : & ItemTree | {
165+ let enabled = |param| item_tree. attrs ( db, krate, param) . is_cfg_enabled ( cfg_options) ;
166+
167+ // In the common case, no parameters will by disabled by `#[cfg]` attributes.
168+ // Therefore, make a first pass to check if all parameters are enabled and, if so,
169+ // clone the `Interned<GenericParams>` instead of recreating an identical copy.
170+ let all_type_or_consts_enabled =
171+ params. type_or_consts . iter ( ) . all ( |( idx, _) | enabled ( idx. into ( ) ) ) ;
172+ let all_lifetimes_enabled = params. lifetimes . iter ( ) . all ( |( idx, _) | enabled ( idx. into ( ) ) ) ;
173+
174+ if all_type_or_consts_enabled && all_lifetimes_enabled {
175+ params. clone ( )
176+ } else {
177+ Interned :: new ( GenericParams {
178+ type_or_consts : all_type_or_consts_enabled
179+ . then ( || params. type_or_consts . clone ( ) )
180+ . unwrap_or_else ( || {
181+ params
182+ . type_or_consts
183+ . iter ( )
184+ . filter_map ( |( idx, param) | {
185+ enabled ( idx. into ( ) ) . then ( || param. clone ( ) )
186+ } )
187+ . collect ( )
188+ } ) ,
189+ lifetimes : all_lifetimes_enabled
190+ . then ( || params. lifetimes . clone ( ) )
191+ . unwrap_or_else ( || {
192+ params
193+ . lifetimes
194+ . iter ( )
195+ . filter_map ( |( idx, param) | {
196+ enabled ( idx. into ( ) ) . then ( || param. clone ( ) )
197+ } )
198+ . collect ( )
199+ } ) ,
200+ where_predicates : params. where_predicates . clone ( ) ,
201+ } )
202+ }
203+ } ;
157204 macro_rules! id_to_generics {
158205 ( $id: ident) => { {
159206 let id = $id. lookup( db) . id;
160207 let tree = id. item_tree( db) ;
161208 let item = & tree[ id. value] ;
162- item. generic_params. clone ( )
209+ enabled_params ( & item. generic_params, & tree )
163210 } } ;
164211 }
165212
@@ -169,7 +216,8 @@ impl GenericParams {
169216 let tree = loc. id . item_tree ( db) ;
170217 let item = & tree[ loc. id . value ] ;
171218
172- let mut generic_params = GenericParams :: clone ( & item. explicit_generic_params ) ;
219+ let enabled_params = enabled_params ( & item. explicit_generic_params , & tree) ;
220+ let mut generic_params = GenericParams :: clone ( & enabled_params) ;
173221
174222 let module = loc. container . module ( db) ;
175223 let func_data = db. function_data ( id) ;
@@ -198,9 +246,14 @@ impl GenericParams {
198246 }
199247 }
200248
201- pub ( crate ) fn fill ( & mut self , lower_ctx : & LowerCtx < ' _ > , node : & dyn HasGenericParams ) {
249+ pub ( crate ) fn fill (
250+ & mut self ,
251+ lower_ctx : & LowerCtx < ' _ > ,
252+ node : & dyn HasGenericParams ,
253+ add_param_attrs : impl FnMut ( AttrOwner , ast:: GenericParam ) ,
254+ ) {
202255 if let Some ( params) = node. generic_param_list ( ) {
203- self . fill_params ( lower_ctx, params)
256+ self . fill_params ( lower_ctx, params, add_param_attrs )
204257 }
205258 if let Some ( where_clause) = node. where_clause ( ) {
206259 self . fill_where_predicates ( lower_ctx, where_clause) ;
@@ -218,7 +271,12 @@ impl GenericParams {
218271 }
219272 }
220273
221- fn fill_params ( & mut self , lower_ctx : & LowerCtx < ' _ > , params : ast:: GenericParamList ) {
274+ fn fill_params (
275+ & mut self ,
276+ lower_ctx : & LowerCtx < ' _ > ,
277+ params : ast:: GenericParamList ,
278+ mut add_param_attrs : impl FnMut ( AttrOwner , ast:: GenericParam ) ,
279+ ) {
222280 for type_or_const_param in params. type_or_const_params ( ) {
223281 match type_or_const_param {
224282 ast:: TypeOrConstParam :: Type ( type_param) => {
@@ -232,13 +290,14 @@ impl GenericParams {
232290 default,
233291 provenance : TypeParamProvenance :: TypeParamList ,
234292 } ;
235- self . type_or_consts . alloc ( param. into ( ) ) ;
293+ let idx = self . type_or_consts . alloc ( param. into ( ) ) ;
236294 let type_ref = TypeRef :: Path ( name. into ( ) ) ;
237295 self . fill_bounds (
238296 lower_ctx,
239297 type_param. type_bound_list ( ) ,
240298 Either :: Left ( type_ref) ,
241299 ) ;
300+ add_param_attrs ( idx. into ( ) , ast:: GenericParam :: TypeParam ( type_param) ) ;
242301 }
243302 ast:: TypeOrConstParam :: Const ( const_param) => {
244303 let name = const_param. name ( ) . map_or_else ( Name :: missing, |it| it. as_name ( ) ) ;
@@ -250,21 +309,23 @@ impl GenericParams {
250309 ty : Interned :: new ( ty) ,
251310 has_default : const_param. default_val ( ) . is_some ( ) ,
252311 } ;
253- self . type_or_consts . alloc ( param. into ( ) ) ;
312+ let idx = self . type_or_consts . alloc ( param. into ( ) ) ;
313+ add_param_attrs ( idx. into ( ) , ast:: GenericParam :: ConstParam ( const_param) ) ;
254314 }
255315 }
256316 }
257317 for lifetime_param in params. lifetime_params ( ) {
258318 let name =
259319 lifetime_param. lifetime ( ) . map_or_else ( Name :: missing, |lt| Name :: new_lifetime ( & lt) ) ;
260320 let param = LifetimeParamData { name : name. clone ( ) } ;
261- self . lifetimes . alloc ( param) ;
321+ let idx = self . lifetimes . alloc ( param) ;
262322 let lifetime_ref = LifetimeRef :: new_name ( name) ;
263323 self . fill_bounds (
264324 lower_ctx,
265325 lifetime_param. type_bound_list ( ) ,
266326 Either :: Right ( lifetime_ref) ,
267327 ) ;
328+ add_param_attrs ( idx. into ( ) , ast:: GenericParam :: LifetimeParam ( lifetime_param) ) ;
268329 }
269330 }
270331
0 commit comments