@@ -6,7 +6,7 @@ use std::num::NonZero;
66use rustc_ast_lowering:: stability:: extern_abi_stability;
77use rustc_data_structures:: fx:: FxIndexMap ;
88use rustc_data_structures:: unord:: { ExtendUnord , UnordMap , UnordSet } ;
9- use rustc_feature:: { EnabledLangFeature , EnabledLibFeature } ;
9+ use rustc_feature:: { EnabledLangFeature , EnabledLibFeature , UNSTABLE_LANG_FEATURES } ;
1010use rustc_hir:: attrs:: { AttributeKind , DeprecatedSince } ;
1111use rustc_hir:: def:: { DefKind , Res } ;
1212use rustc_hir:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE , LocalDefId , LocalModDefId } ;
@@ -1093,8 +1093,36 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
10931093 }
10941094 }
10951095
1096- for ( feature, span) in remaining_lib_features {
1097- tcx. dcx ( ) . emit_err ( errors:: UnknownFeature { span, feature } ) ;
1096+ if !remaining_lib_features. is_empty ( ) {
1097+ let lang_features =
1098+ UNSTABLE_LANG_FEATURES . iter ( ) . map ( |feature| feature. name ) . collect :: < Vec < _ > > ( ) ;
1099+ let lib_features = tcx
1100+ . crates ( ( ) )
1101+ . into_iter ( )
1102+ . flat_map ( |& cnum| {
1103+ tcx. lib_features ( cnum) . stability . keys ( ) . copied ( ) . into_sorted_stable_ord ( )
1104+ } )
1105+ . collect :: < Vec < _ > > ( ) ;
1106+
1107+ let valid_feature_names = [ lang_features, lib_features] . concat ( ) ;
1108+
1109+ for ( feature, span) in remaining_lib_features {
1110+ let suggestion = feature. find_similar ( & valid_feature_names) ;
1111+ match suggestion {
1112+ Some ( ( actual_name, _) ) => {
1113+ let misspelled_name = feature;
1114+ tcx. dcx ( ) . emit_err ( errors:: MisspelledFeature {
1115+ span,
1116+ misspelled_name,
1117+ actual_name,
1118+ suggestion : span,
1119+ } ) ;
1120+ }
1121+ None => {
1122+ tcx. dcx ( ) . emit_err ( errors:: UnknownFeature { span, feature } ) ;
1123+ }
1124+ }
1125+ }
10981126 }
10991127
11001128 for ( & implied_by, & feature) in remaining_implications. to_sorted_stable_ord ( ) {
0 commit comments