11//! Concrete error types for all operations which may be invalid in a certain const context.
22
33use hir:: { ConstContext , LangItem } ;
4- use rustc_errors:: Diag ;
54use rustc_errors:: codes:: * ;
5+ use rustc_errors:: { Applicability , Diag , MultiSpan } ;
66use rustc_hir as hir;
77use rustc_hir:: def_id:: DefId ;
88use rustc_infer:: infer:: TyCtxtInferExt ;
@@ -11,8 +11,8 @@ use rustc_middle::mir::CallSource;
1111use rustc_middle:: span_bug;
1212use rustc_middle:: ty:: print:: { PrintTraitRefExt as _, with_no_trimmed_paths} ;
1313use rustc_middle:: ty:: {
14- self , Closure , FnDef , FnPtr , GenericArgKind , GenericArgsRef , Param , TraitRef , Ty ,
15- suggest_constraining_type_param,
14+ self , AssocContainer , Closure , FnDef , FnPtr , GenericArgKind , GenericArgsRef , Param , TraitRef ,
15+ Ty , suggest_constraining_type_param,
1616} ;
1717use rustc_session:: parse:: add_feature_diagnostics;
1818use rustc_span:: { BytePos , Pos , Span , Symbol , sym} ;
@@ -352,18 +352,71 @@ fn build_error_for_const_call<'tcx>(
352352 non_or_conditionally,
353353 } )
354354 }
355- _ => ccx. dcx ( ) . create_err ( errors:: NonConstFnCall {
356- span,
357- def_descr : ccx. tcx . def_descr ( callee) ,
358- def_path_str : ccx. tcx . def_path_str_with_args ( callee, args) ,
359- kind : ccx. const_kind ( ) ,
360- non_or_conditionally,
361- } ) ,
355+ _ => {
356+ let def_descr = ccx. tcx . def_descr ( callee) ;
357+ let mut err = ccx. dcx ( ) . create_err ( errors:: NonConstFnCall {
358+ span,
359+ def_descr,
360+ def_path_str : ccx. tcx . def_path_str_with_args ( callee, args) ,
361+ kind : ccx. const_kind ( ) ,
362+ non_or_conditionally,
363+ } ) ;
364+ if let Some ( item) = ccx. tcx . opt_associated_item ( callee) {
365+ if let AssocContainer :: Trait = item. container
366+ && let parent = item. container_id ( ccx. tcx )
367+ && !ccx. tcx . is_const_trait ( parent)
368+ {
369+ let assoc_span = ccx. tcx . def_span ( callee) ;
370+ let assoc_name = ccx. tcx . item_name ( callee) ;
371+ let mut span: MultiSpan = ccx. tcx . def_span ( parent) . into ( ) ;
372+ span. push_span_label ( assoc_span, format ! ( "this {def_descr} is not const" ) ) ;
373+ let trait_descr = ccx. tcx . def_descr ( parent) ;
374+ let trait_span = ccx. tcx . def_span ( parent) ;
375+ let trait_name = ccx. tcx . item_name ( parent) ;
376+ span. push_span_label ( trait_span, format ! ( "this {trait_descr} is not const" ) ) ;
377+ err. span_note (
378+ span,
379+ format ! (
380+ "{def_descr} `{assoc_name}` is not const because {trait_descr} \
381+ `{trait_name}` is not const",
382+ ) ,
383+ ) ;
384+ if parent. is_local ( ) && ccx. tcx . sess . is_nightly_build ( ) {
385+ if !ccx. tcx . features ( ) . const_trait_impl ( ) {
386+ err. help (
387+ "add `#![feature(const_trait_impl)]` to the crate attributes to \
388+ enable `#[const_trait]`",
389+ ) ;
390+ }
391+ let indentation = ccx
392+ . tcx
393+ . sess
394+ . source_map ( )
395+ . indentation_before ( trait_span)
396+ . unwrap_or_default ( ) ;
397+ err. span_suggestion_verbose (
398+ trait_span. shrink_to_lo ( ) ,
399+ format ! ( "consider making trait `{trait_name}` const" ) ,
400+ format ! ( "#[const_trait]\n {indentation}" ) ,
401+ Applicability :: MaybeIncorrect ,
402+ ) ;
403+ } else if !ccx. tcx . sess . is_nightly_build ( ) {
404+ err. help ( "const traits are not yet supported on stable Rust" ) ;
405+ }
406+ }
407+ } else if ccx. tcx . constness ( callee) != hir:: Constness :: Const {
408+ let name = ccx. tcx . item_name ( callee) ;
409+ err. span_note (
410+ ccx. tcx . def_span ( callee) ,
411+ format ! ( "{def_descr} `{name}` is not const" ) ,
412+ ) ;
413+ }
414+ err
415+ }
362416 } ;
363417
364418 err. note ( format ! (
365- "calls in {}s are limited to constant functions, \
366- tuple structs and tuple variants",
419+ "calls in {}s are limited to constant functions, tuple structs and tuple variants" ,
367420 ccx. const_kind( ) ,
368421 ) ) ;
369422
0 commit comments