|
1 | | -use std::borrow::Cow; |
2 | 1 | use std::hash::Hash; |
3 | 2 | use std::path::PathBuf; |
4 | 3 | use std::sync::{Arc, OnceLock as OnceCell}; |
@@ -485,7 +484,7 @@ impl Item { |
485 | 484 | name, |
486 | 485 | kind, |
487 | 486 | Attributes::from_hir(hir_attrs), |
488 | | - hir_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), |
| 487 | + extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg), |
489 | 488 | ) |
490 | 489 | } |
491 | 490 |
|
@@ -985,147 +984,107 @@ pub(crate) struct Module { |
985 | 984 | pub(crate) span: Span, |
986 | 985 | } |
987 | 986 |
|
988 | | -pub(crate) trait AttributesExt { |
989 | | - type AttributeIterator<'a>: Iterator<Item = ast::MetaItemInner> |
990 | | - where |
991 | | - Self: 'a; |
992 | | - type Attributes<'a>: Iterator<Item = &'a hir::Attribute> |
993 | | - where |
994 | | - Self: 'a; |
995 | | - |
996 | | - fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_>; |
997 | | - |
998 | | - fn iter(&self) -> Self::Attributes<'_>; |
999 | | - |
1000 | | - fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> { |
1001 | | - let sess = tcx.sess; |
1002 | | - let doc_cfg_active = tcx.features().doc_cfg(); |
1003 | | - let doc_auto_cfg_active = tcx.features().doc_auto_cfg(); |
1004 | | - |
1005 | | - fn single<T: IntoIterator>(it: T) -> Option<T::Item> { |
1006 | | - let mut iter = it.into_iter(); |
1007 | | - let item = iter.next()?; |
1008 | | - if iter.next().is_some() { |
1009 | | - return None; |
1010 | | - } |
1011 | | - Some(item) |
| 987 | +pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>( |
| 988 | + attrs: I, |
| 989 | + name: Symbol, |
| 990 | +) -> impl Iterator<Item = ast::MetaItemInner> + use<'a, I> { |
| 991 | + attrs |
| 992 | + .into_iter() |
| 993 | + .filter(move |attr| attr.has_name(name)) |
| 994 | + .filter_map(ast::attr::AttributeExt::meta_item_list) |
| 995 | + .flatten() |
| 996 | +} |
| 997 | + |
| 998 | +pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>( |
| 999 | + attrs: I, |
| 1000 | + tcx: TyCtxt<'_>, |
| 1001 | + hidden_cfg: &FxHashSet<Cfg>, |
| 1002 | +) -> Option<Arc<Cfg>> { |
| 1003 | + let sess = tcx.sess; |
| 1004 | + let doc_cfg_active = tcx.features().doc_cfg(); |
| 1005 | + let doc_auto_cfg_active = tcx.features().doc_auto_cfg(); |
| 1006 | + |
| 1007 | + fn single<T: IntoIterator>(it: T) -> Option<T::Item> { |
| 1008 | + let mut iter = it.into_iter(); |
| 1009 | + let item = iter.next()?; |
| 1010 | + if iter.next().is_some() { |
| 1011 | + return None; |
1012 | 1012 | } |
| 1013 | + Some(item) |
| 1014 | + } |
1013 | 1015 |
|
1014 | | - let mut cfg = if doc_cfg_active || doc_auto_cfg_active { |
1015 | | - let mut doc_cfg = self |
1016 | | - .iter() |
1017 | | - .filter(|attr| attr.has_name(sym::doc)) |
1018 | | - .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) |
| 1016 | + let mut cfg = if doc_cfg_active || doc_auto_cfg_active { |
| 1017 | + let mut doc_cfg = attrs |
| 1018 | + .clone() |
| 1019 | + .filter(|attr| attr.has_name(sym::doc)) |
| 1020 | + .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) |
| 1021 | + .filter(|attr| attr.has_name(sym::cfg)) |
| 1022 | + .peekable(); |
| 1023 | + if doc_cfg.peek().is_some() && doc_cfg_active { |
| 1024 | + doc_cfg |
| 1025 | + .filter_map(|attr| Cfg::parse(&attr).ok()) |
| 1026 | + .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) |
| 1027 | + } else if doc_auto_cfg_active { |
| 1028 | + // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because |
| 1029 | + // `doc(cfg())` overrides `cfg()`). |
| 1030 | + attrs |
| 1031 | + .clone() |
1019 | 1032 | .filter(|attr| attr.has_name(sym::cfg)) |
1020 | | - .peekable(); |
1021 | | - if doc_cfg.peek().is_some() && doc_cfg_active { |
1022 | | - doc_cfg |
1023 | | - .filter_map(|attr| Cfg::parse(&attr).ok()) |
1024 | | - .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) |
1025 | | - } else if doc_auto_cfg_active { |
1026 | | - // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because |
1027 | | - // `doc(cfg())` overrides `cfg()`). |
1028 | | - self.iter() |
1029 | | - .filter(|attr| attr.has_name(sym::cfg)) |
1030 | | - .filter_map(|attr| single(attr.meta_item_list()?)) |
1031 | | - .filter_map(|attr| { |
1032 | | - Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten() |
1033 | | - }) |
1034 | | - .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) |
1035 | | - } else { |
1036 | | - Cfg::True |
1037 | | - } |
| 1033 | + .filter_map(|attr| single(attr.meta_item_list()?)) |
| 1034 | + .filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()) |
| 1035 | + .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) |
1038 | 1036 | } else { |
1039 | 1037 | Cfg::True |
1040 | | - }; |
1041 | | - |
1042 | | - for attr in self.iter() { |
1043 | | - // #[doc] |
1044 | | - if attr.doc_str().is_none() && attr.has_name(sym::doc) { |
1045 | | - // #[doc(...)] |
1046 | | - if let Some(list) = attr.meta_item_list() { |
1047 | | - for item in list { |
1048 | | - // #[doc(hidden)] |
1049 | | - if !item.has_name(sym::cfg) { |
1050 | | - continue; |
1051 | | - } |
1052 | | - // #[doc(cfg(...))] |
1053 | | - if let Some(cfg_mi) = item |
1054 | | - .meta_item() |
1055 | | - .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) |
1056 | | - { |
1057 | | - match Cfg::parse(cfg_mi) { |
1058 | | - Ok(new_cfg) => cfg &= new_cfg, |
1059 | | - Err(e) => { |
1060 | | - sess.dcx().span_err(e.span, e.msg); |
1061 | | - } |
| 1038 | + } |
| 1039 | + } else { |
| 1040 | + Cfg::True |
| 1041 | + }; |
| 1042 | + |
| 1043 | + for attr in attrs.clone() { |
| 1044 | + // #[doc] |
| 1045 | + if attr.doc_str().is_none() && attr.has_name(sym::doc) { |
| 1046 | + // #[doc(...)] |
| 1047 | + if let Some(list) = attr.meta_item_list() { |
| 1048 | + for item in list { |
| 1049 | + // #[doc(hidden)] |
| 1050 | + if !item.has_name(sym::cfg) { |
| 1051 | + continue; |
| 1052 | + } |
| 1053 | + // #[doc(cfg(...))] |
| 1054 | + if let Some(cfg_mi) = item |
| 1055 | + .meta_item() |
| 1056 | + .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) |
| 1057 | + { |
| 1058 | + match Cfg::parse(cfg_mi) { |
| 1059 | + Ok(new_cfg) => cfg &= new_cfg, |
| 1060 | + Err(e) => { |
| 1061 | + sess.dcx().span_err(e.span, e.msg); |
1062 | 1062 | } |
1063 | 1063 | } |
1064 | 1064 | } |
1065 | 1065 | } |
1066 | 1066 | } |
1067 | 1067 | } |
| 1068 | + } |
1068 | 1069 |
|
1069 | | - // treat #[target_feature(enable = "feat")] attributes as if they were |
1070 | | - // #[doc(cfg(target_feature = "feat"))] attributes as well |
1071 | | - for attr in self.lists(sym::target_feature) { |
1072 | | - if attr.has_name(sym::enable) { |
1073 | | - if attr.value_str().is_some() { |
1074 | | - // Clone `enable = "feat"`, change to `target_feature = "feat"`. |
1075 | | - // Unwrap is safe because `value_str` succeeded above. |
1076 | | - let mut meta = attr.meta_item().unwrap().clone(); |
1077 | | - meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature)); |
1078 | | - |
1079 | | - if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) { |
1080 | | - cfg &= feat_cfg; |
1081 | | - } |
| 1070 | + // treat #[target_feature(enable = "feat")] attributes as if they were |
| 1071 | + // #[doc(cfg(target_feature = "feat"))] attributes as well |
| 1072 | + for attr in hir_attr_lists(attrs, sym::target_feature) { |
| 1073 | + if attr.has_name(sym::enable) { |
| 1074 | + if attr.value_str().is_some() { |
| 1075 | + // Clone `enable = "feat"`, change to `target_feature = "feat"`. |
| 1076 | + // Unwrap is safe because `value_str` succeeded above. |
| 1077 | + let mut meta = attr.meta_item().unwrap().clone(); |
| 1078 | + meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature)); |
| 1079 | + |
| 1080 | + if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) { |
| 1081 | + cfg &= feat_cfg; |
1082 | 1082 | } |
1083 | 1083 | } |
1084 | 1084 | } |
1085 | | - |
1086 | | - if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) } |
1087 | 1085 | } |
1088 | | -} |
1089 | | - |
1090 | | -impl AttributesExt for [hir::Attribute] { |
1091 | | - type AttributeIterator<'a> = impl Iterator<Item = ast::MetaItemInner> + 'a; |
1092 | | - type Attributes<'a> = impl Iterator<Item = &'a hir::Attribute> + 'a; |
1093 | 1086 |
|
1094 | | - fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> { |
1095 | | - self.iter() |
1096 | | - .filter(move |attr| attr.has_name(name)) |
1097 | | - .filter_map(ast::attr::AttributeExt::meta_item_list) |
1098 | | - .flatten() |
1099 | | - } |
1100 | | - |
1101 | | - fn iter(&self) -> Self::Attributes<'_> { |
1102 | | - self.iter() |
1103 | | - } |
1104 | | -} |
1105 | | - |
1106 | | -impl AttributesExt for [(Cow<'_, hir::Attribute>, Option<DefId>)] { |
1107 | | - type AttributeIterator<'a> |
1108 | | - = impl Iterator<Item = ast::MetaItemInner> + 'a |
1109 | | - where |
1110 | | - Self: 'a; |
1111 | | - type Attributes<'a> |
1112 | | - = impl Iterator<Item = &'a hir::Attribute> + 'a |
1113 | | - where |
1114 | | - Self: 'a; |
1115 | | - |
1116 | | - fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> { |
1117 | | - AttributesExt::iter(self) |
1118 | | - .filter(move |attr| attr.has_name(name)) |
1119 | | - .filter_map(hir::Attribute::meta_item_list) |
1120 | | - .flatten() |
1121 | | - } |
1122 | | - |
1123 | | - fn iter(&self) -> Self::Attributes<'_> { |
1124 | | - self.iter().map(move |(attr, _)| match attr { |
1125 | | - Cow::Borrowed(attr) => *attr, |
1126 | | - Cow::Owned(attr) => attr, |
1127 | | - }) |
1128 | | - } |
| 1087 | + if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) } |
1129 | 1088 | } |
1130 | 1089 |
|
1131 | 1090 | pub(crate) trait NestedAttributesExt { |
@@ -1191,7 +1150,7 @@ pub(crate) struct Attributes { |
1191 | 1150 |
|
1192 | 1151 | impl Attributes { |
1193 | 1152 | pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> + '_ { |
1194 | | - self.other_attrs.lists(name) |
| 1153 | + hir_attr_lists(&self.other_attrs[..], name) |
1195 | 1154 | } |
1196 | 1155 |
|
1197 | 1156 | pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool { |
@@ -1258,7 +1217,9 @@ impl Attributes { |
1258 | 1217 | pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> { |
1259 | 1218 | let mut aliases = FxIndexSet::default(); |
1260 | 1219 |
|
1261 | | - for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) { |
| 1220 | + for attr in |
| 1221 | + hir_attr_lists(&self.other_attrs[..], sym::doc).filter(|a| a.has_name(sym::alias)) |
| 1222 | + { |
1262 | 1223 | if let Some(values) = attr.meta_item_list() { |
1263 | 1224 | for l in values { |
1264 | 1225 | if let Some(lit) = l.lit() |
|
0 commit comments