pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);

    if tcx.stability().staged_api[&LOCAL_CRATE] {
        let krate = tcx.hir().krate();
        let mut missing = MissingStabilityAnnotations { tcx, access_levels };
        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span);
        intravisit::walk_crate(&mut missing, krate);
        krate.visit_all_item_likes(&mut missing.as_deep_visitor());
    }

    let declared_lang_features = &tcx.features().declared_lang_features;
    let mut lang_features = FxHashSet::default();
    for &(feature, span, since) in declared_lang_features {
        if let Some(since) = since {
            // Warn if the user has enabled an already-stable lang feature.
            unnecessary_stable_feature_lint(tcx, span, feature, since);
        }
        if !lang_features.insert(feature) {
            // Warn if the user enables a lang feature multiple times.
            duplicate_feature_err(tcx.sess, span, feature);
        }
    }

    let declared_lib_features = &tcx.features().declared_lib_features;
    let mut remaining_lib_features = FxHashMap::default();
    for (feature, span) in declared_lib_features {
        if remaining_lib_features.contains_key(&feature) {
            // Warn if the user enables a lib feature multiple times.
            duplicate_feature_err(tcx.sess, *span, *feature);
        }
        remaining_lib_features.insert(feature, *span);
    }
    // `stdbuild` has special handling for `libc`, so we need to
    // recognise the feature when building std.
    // Likewise, libtest is handled specially, so `test` isn't
    // available as we'd like it to be.
    // FIXME: only remove `libc` when `stdbuild` is active.
    // FIXME: remove special casing for `test`.
    remaining_lib_features.remove(&Symbol::intern("libc"));
    remaining_lib_features.remove(&sym::test);

    let check_features = |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| {
        for &(feature, since) in defined_features {
            if let Some(since) = since {
                if let Some(span) = remaining_lib_features.get(&feature) {
                    // Warn if the user has enabled an already-stable lib feature.
                    unnecessary_stable_feature_lint(tcx, *span, feature, since);
                }
            }
            remaining_lib_features.remove(&feature);
            if remaining_lib_features.is_empty() {
                break;
            }
        }
    };

    // We always collect the lib features declared in the current crate, even if there are
    // no unknown features, because the collection also does feature attribute validation.
    let local_defined_features = tcx.lib_features().to_vec();
    if !remaining_lib_features.is_empty() {
        check_features(&mut remaining_lib_features, &local_defined_features);

        for &cnum in &*tcx.crates() {
            if remaining_lib_features.is_empty() {
                break;
            }
            check_features(&mut remaining_lib_features, tcx.defined_lib_features(cnum));
        }
    }

    for (feature, span) in remaining_lib_features {
        struct_span_err!(tcx.sess, span, E0635, "unknown feature `{}`", feature).emit();
    }

    // FIXME(#44232): the `used_features` table no longer exists, so we
    // don't lint about unused features. We should re-enable this one day!
}
/// Given the list of enabled features that were not language features (i.e., that
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
Given the list of enabled features that were not language features , and the list of features used from
libraries, identify activated features that don't exist and error about them.
Given the list of enabled features that were not language features and the list of features used from libraries identify activated features that don ' t exist and error about them .
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
    let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
    if tcx.stability().staged_api[&LOCAL_CRATE] {
        let krate = tcx.hir().krate();
        let mut missing = MissingStabilityAnnotations { tcx, access_levels };
        missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span);
        intravisit::walk_crate(&mut missing, krate);
        krate.visit_all_item_likes(&mut missing.as_deep_visitor());
    }
    let declared_lang_features = &tcx.features().declared_lang_features;
    let mut lang_features = FxHashSet::default();
    for &(feature, span, since) in declared_lang_features {
        if let Some(since) = since {
            // Warn if the user has enabled an already-stable lang feature.
            unnecessary_stable_feature_lint(tcx, span, feature, since);
        }
        if !lang_features.insert(feature) {
            // Warn if the user enables a lang feature multiple times.
            duplicate_feature_err(tcx.sess, span, feature);
        }
    }
    let declared_lib_features = &tcx.features().declared_lib_features;
    let mut remaining_lib_features = FxHashMap::default();
    for (feature, span) in declared_lib_features {
        if remaining_lib_features.contains_key(&feature) {
            // Warn if the user enables a lib feature multiple times.
            duplicate_feature_err(tcx.sess, *span, *feature);
        }
        remaining_lib_features.insert(feature, *span);
    }
    // `stdbuild` has special handling for `libc`, so we need to
    // recognise the feature when building std.
    // Likewise, libtest is handled specially, so `test` isn't
    // available as we'd like it to be.
    // FIXME: only remove `libc` when `stdbuild` is active.
    // FIXME: remove special casing for `test`.
    remaining_lib_features.remove(&Symbol::intern("libc"));
    remaining_lib_features.remove(&sym::test);
    let check_features = |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| {
        for &(feature, since) in defined_features {
            if let Some(since) = since {
                if let Some(span) = remaining_lib_features.get(&feature) {
                    // Warn if the user has enabled an already-stable lib feature.
                    unnecessary_stable_feature_lint(tcx, *span, feature, since);
                }
            }
            remaining_lib_features.remove(&feature);
            if remaining_lib_features.is_empty() {
                break;
            }
        }
    };
    // We always collect the lib features declared in the current crate, even if there are
    // no unknown features, because the collection also does feature attribute validation.
    let local_defined_features = tcx.lib_features().to_vec();
    if !remaining_lib_features.is_empty() {
        check_features(&mut remaining_lib_features, &local_defined_features);
        for &cnum in &*tcx.crates() {
            if remaining_lib_features.is_empty() {
                break;
            }
            check_features(&mut remaining_lib_features, tcx.defined_lib_features(cnum));
        }
    }
    for (feature, span) in remaining_lib_features {
        struct_span_err!(tcx.sess, span, E0635, "unknown feature `{}`", feature).emit();
    }
    // FIXME(#44232): the `used_features` table no longer exists, so we
    // don't lint about unused features. We should re-enable this one day!
}
pub fn check_unused_or_stable_features ( tcx : TyCtxt < ' _ > ) { let access_levels = & tcx . privacy_access_levels ( LOCAL_CRATE ) ; if tcx . stability ( ) . staged_api [ & LOCAL_CRATE ] { let krate = tcx . hir ( ) . krate ( ) ; let mut missing = MissingStabilityAnnotations { tcx , access_levels } ; missing . check_missing_stability ( hir :: CRATE_HIR_ID , krate . item . span ) ; intravisit :: walk_crate ( & mut missing , krate ) ; krate . visit_all_item_likes ( & mut missing . as_deep_visitor ( ) ) ; } let declared_lang_features = & tcx . features ( ) . declared_lang_features ; let mut lang_features = FxHashSet :: default ( ) ; for & ( feature , span , since ) in declared_lang_features { if let Some ( since ) = since { // Warn if the user has enabled an already-stable lang feature. unnecessary_stable_feature_lint ( tcx , span , feature , since ) ; } if ! lang_features . insert ( feature ) { // Warn if the user enables a lang feature multiple times. duplicate_feature_err ( tcx . sess , span , feature ) ; } } let declared_lib_features = & tcx . features ( ) . declared_lib_features ; let mut remaining_lib_features = FxHashMap :: default ( ) ; for ( feature , span ) in declared_lib_features { if remaining_lib_features . contains_key ( & feature ) { // Warn if the user enables a lib feature multiple times. duplicate_feature_err ( tcx . sess , * span , * feature ) ; } remaining_lib_features . insert ( feature , * span ) ; } // `stdbuild` has special handling for `libc`, so we need to // recognise the feature when building std. // Likewise, libtest is handled specially, so `test` isn't // available as we'd like it to be. // FIXME: only remove `libc` when `stdbuild` is active. // FIXME: remove special casing for `test`. remaining_lib_features . remove ( & Symbol :: intern ( " " ) ) ; remaining_lib_features . remove ( & sym :: test ) ; let check_features = | remaining_lib_features : & mut FxHashMap < _ , _ > , defined_features : & [ _ ] | { for & ( feature , since ) in defined_features { if let Some ( since ) = since { if let Some ( span ) = remaining_lib_features . get ( & feature ) { // Warn if the user has enabled an already-stable lib feature. unnecessary_stable_feature_lint ( tcx , * span , feature , since ) ; } } remaining_lib_features . remove ( & feature ) ; if remaining_lib_features . is_empty ( ) { break ; } } } ; // We always collect the lib features declared in the current crate, even if there are // no unknown features, because the collection also does feature attribute validation. let local_defined_features = tcx . lib_features ( ) . to_vec ( ) ; if ! remaining_lib_features . is_empty ( ) { check_features ( & mut remaining_lib_features , & local_defined_features ) ; for & cnum in & * tcx . crates ( ) { if remaining_lib_features . is_empty ( ) { break ; } check_features ( & mut remaining_lib_features , tcx . defined_lib_features ( cnum ) ) ; } } for ( feature , span ) in remaining_lib_features { struct_span_err ! ( tcx sess span E0635 " " feature ) . emit ( ) ; } // FIXME(#44232): the `used_features` table no longer exists, so we // don't lint about unused features. We should re-enable this one day! }
Given the list of enabled features that were not language features (i.e., that
were expected to be library features), and the list of features used from
libraries, identify activated features that don't exist and error about them.
Given the list of enabled features that were not language features ( i . e . that were expected to be library features ) and the list of features used from libraries identify activated features that don ' t exist and error about them .
tcx
TyCtxt<'_>
tcx
TyCtxt<'_>