Change:
Currently, there in tidy that ensures that there is no library feature and language feature of the same name. Its presence in the documentation above. This check since , and has caused multiple additions that have both library and language components to be split up: / / / PR has challenged the status quo, by reusing the lang feature inside libraries provided to programs. It actually to the tidy check in order to get it passing. There has been about this in the thread of and the resolution was to allow to share the feature gate. So my question is: which purpose does this check serve? should the check be present, or should it be abolished? Should the feature gate be split up into a library component and a lang component?
IMO we should just kill the tidy check. For inclusive ranges we are stabilizing the lib and syntax separately, but if they had been under the same gate it would have been easy to split them up, like we are doing for const fn.
I too think we should lump things that are "the same underlying concept" under one feature gate.
Looks like the original code allowed for a 'joint features' whitelist, so it seems like it might have just been a sanity check that any intersection was intentional. Indeed, that script actually says that it's for doing some sanity checks. If for some reason that sanity check is still desirable, at minimum I'd be +1 to creating a whitelist rather than ad-hoc growing the if condition.
We can guard from that by doing a check for any joint features whether the tracking issue and stability status (stable or unstable) matches between lib and lang features.

Discussion:
pub tracking_issue: Option<u32>, } <ins> impl Feature { fn check_match(&self, other: &Feature)-> Result<(), Vec<&'static str>> { let mut mismatches = Vec::new(); if self.level != other.level { mismatches.push("stability level"); } if self.level == Status::Stable || other.level == Status::Stable { // As long as a feature is unstable, the since field tracks // when the given part of the feature has been implemented. // Mismatches are tolerable as features evolve and functionality // gets added. // Once a feature is stable, the since field tracks the first version // it was part of the stable distribution, and mismatches are disallowed. if self.since != other.since { mismatches.push("since"); } } if self.tracking_issue != other.tracking_issue { mismatches.push("tracking issue"); } if mismatches.is_empty() { Ok(()) } else { Err(mismatches) } } } </ins> pub type Features = HashMap<String, Feature>; pub fn check(path: &Path, bad: &mut bool, quiet: bool) {

&mut |res, file, line| { match res { Ok((name, f)) => { <del> let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), line, msg); }; if lang_features.contains_key(name) && name != "proc_macro" { err("duplicating a lang feature"); } if let Some(ref s) = lib_features.get(name) { if s.level != f.level { err("different stability level than before"); } if s.since != f.since { err("different `since` than before"); </del> <ins> let mut check_features = |f: &Feature, list: &Features, display: &str| { if let Some(ref s) = list.get(name) { if let Err(m) = (&f).check_match(s) { tidy_error!(bad, "{}:{}: mismatches to {} in: {:?}", file.display(), line, display, &m); } </ins> } <del> if s.tracking_issue != f.tracking_issue { err("different `tracking_issue` than before"); } } </del> <ins> }; check_features(&f, &lang_features, "corresponding lang feature"); check_features(&f, &lib_features, "previous"); </ins> lib_features.insert(name.to_owned(), f); }, Err(msg) => {