@@ -41,7 +41,7 @@ pub use coercion::can_coerce;
4141use fn_ctxt:: FnCtxt ;
4242use rustc_data_structures:: unord:: UnordSet ;
4343use rustc_errors:: codes:: * ;
44- use rustc_errors:: { Applicability , ErrorGuaranteed , pluralize, struct_span_code_err} ;
44+ use rustc_errors:: { Applicability , Diag , ErrorGuaranteed , pluralize, struct_span_code_err} ;
4545use rustc_hir as hir;
4646use rustc_hir:: def:: { DefKind , Res } ;
4747use rustc_hir:: { HirId , HirIdMap , Node } ;
@@ -204,7 +204,9 @@ fn typeck_with_inspect<'tcx>(
204204 ) ;
205205 }
206206
207- fcx. check_expr_coercible_to_type ( body. value , expected_type, None ) ;
207+ fcx. check_expr_coercible_to_type_or_error ( body. value , expected_type, None , |err, _| {
208+ extend_err_with_const_context ( err, tcx, node, expected_type) ;
209+ } ) ;
208210
209211 fcx. write_ty ( id, expected_type) ;
210212 } ;
@@ -274,6 +276,126 @@ fn typeck_with_inspect<'tcx>(
274276 typeck_results
275277}
276278
279+ fn extend_err_with_const_context (
280+ err : & mut Diag < ' _ > ,
281+ tcx : TyCtxt < ' _ > ,
282+ node : hir:: Node < ' _ > ,
283+ expected_ty : Ty < ' _ > ,
284+ ) {
285+ match node {
286+ hir:: Node :: ImplItem ( hir:: ImplItem { kind : hir:: ImplItemKind :: Const ( ty, _) , .. } )
287+ | hir:: Node :: TraitItem ( hir:: TraitItem {
288+ kind : hir:: TraitItemKind :: Const ( ty, _, _) , ..
289+ } ) => {
290+ // Point at the `Type` in `const NAME: Type = value;`.
291+ err. span_label ( ty. span , "expected because of the type of the associated constant" ) ;
292+ }
293+ hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Const ( _, _, ty, _) , .. } ) => {
294+ // Point at the `Type` in `const NAME: Type = value;`.
295+ err. span_label ( ty. span , "expected because of the type of the constant" ) ;
296+ }
297+ hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Static ( _, _, ty, _) , .. } ) => {
298+ // Point at the `Type` in `static NAME: Type = value;`.
299+ err. span_label ( ty. span , "expected because of the type of the static" ) ;
300+ }
301+ hir:: Node :: AnonConst ( anon)
302+ if let hir:: Node :: ConstArg ( parent) = tcx. parent_hir_node ( anon. hir_id )
303+ && let hir:: Node :: Ty ( parent) = tcx. parent_hir_node ( parent. hir_id )
304+ && let hir:: TyKind :: Array ( _ty, _len) = parent. kind =>
305+ {
306+ // `[type; len]` in type context.
307+ err. note ( "array length can only be `usize`" ) ;
308+ }
309+ hir:: Node :: AnonConst ( anon)
310+ if let hir:: Node :: ConstArg ( parent) = tcx. parent_hir_node ( anon. hir_id )
311+ && let hir:: Node :: Expr ( parent) = tcx. parent_hir_node ( parent. hir_id )
312+ && let hir:: ExprKind :: Repeat ( _ty, _len) = parent. kind =>
313+ {
314+ // `[type; len]` in expr context.
315+ err. note ( "array length can only be `usize`" ) ;
316+ }
317+ // FIXME: support method calls too.
318+ hir:: Node :: AnonConst ( anon)
319+ if let hir:: Node :: ConstArg ( parent) = tcx. parent_hir_node ( anon. hir_id )
320+ && let hir:: Node :: Expr ( expr) = tcx. parent_hir_node ( parent. hir_id )
321+ && let hir:: ExprKind :: Path ( path) = expr. kind
322+ && let hir:: QPath :: Resolved ( _, path) = path
323+ && let Res :: Def ( _, def_id) = path. res =>
324+ {
325+ // `foo<N>()` in expression context, point at `foo`'s const parameter.
326+ if let Some ( i) =
327+ path. segments . iter ( ) . last ( ) . and_then ( |segment| segment. args ) . and_then ( |args| {
328+ args. args . iter ( ) . position ( |arg| {
329+ matches ! ( arg, hir:: GenericArg :: Const ( arg) if arg. hir_id == parent. hir_id)
330+ } )
331+ } )
332+ {
333+ let generics = tcx. generics_of ( def_id) ;
334+ let param = & generics. param_at ( i, tcx) ;
335+ let sp = tcx. def_span ( param. def_id ) ;
336+ err. span_note ( sp, "expected because of the type of the const parameter" ) ;
337+ }
338+ }
339+ hir:: Node :: AnonConst ( anon)
340+ if let hir:: Node :: ConstArg ( parent) = tcx. parent_hir_node ( anon. hir_id )
341+ && let hir:: Node :: Ty ( ty) = tcx. parent_hir_node ( parent. hir_id )
342+ && let hir:: TyKind :: Path ( path) = ty. kind
343+ && let hir:: QPath :: Resolved ( _, path) = path
344+ && let Res :: Def ( _, def_id) = path. res =>
345+ {
346+ // `Foo<N>` in type context, point at `Foo`'s const parameter.
347+ if let Some ( i) =
348+ path. segments . iter ( ) . last ( ) . and_then ( |segment| segment. args ) . and_then ( |args| {
349+ args. args . iter ( ) . position ( |arg| {
350+ matches ! ( arg, hir:: GenericArg :: Const ( arg) if arg. hir_id == parent. hir_id)
351+ } )
352+ } )
353+ {
354+ let generics = tcx. generics_of ( def_id) ;
355+ let param = & generics. param_at ( i, tcx) ;
356+ let sp = tcx. def_span ( param. def_id ) ;
357+ err. span_note ( sp, "expected because of the type of the const parameter" ) ;
358+ }
359+ }
360+ hir:: Node :: AnonConst ( anon)
361+ if let hir:: Node :: Variant ( _variant) = tcx. parent_hir_node ( anon. hir_id ) =>
362+ {
363+ // FIXME: point at `repr` when present in the type.
364+ err. note (
365+ "enum variant discriminant can only be of a primitive type compatible with the \
366+ enum's `repr`",
367+ ) ;
368+ }
369+ hir:: Node :: AnonConst ( anon)
370+ if let hir:: Node :: ConstArg ( parent) = tcx. parent_hir_node ( anon. hir_id )
371+ && let hir:: Node :: GenericParam ( param) = tcx. parent_hir_node ( parent. hir_id )
372+ && let hir:: GenericParamKind :: Const { ty, .. } = param. kind =>
373+ {
374+ // `fn foo<const N: usize = ()>` point at the `usize`.
375+ err. span_label ( ty. span , "expected because of the type of the const parameter" ) ;
376+ }
377+ hir:: Node :: AnonConst ( anon)
378+ if let hir:: Node :: ConstArg ( parent) = tcx. parent_hir_node ( anon. hir_id )
379+ && let hir:: Node :: TyPat ( ty_pat) = tcx. parent_hir_node ( parent. hir_id )
380+ && let hir:: Node :: Ty ( ty) = tcx. parent_hir_node ( ty_pat. hir_id )
381+ && let hir:: TyKind :: Pat ( ty, _) = ty. kind =>
382+ {
383+ // Point at `char` in `pattern_type!(char is 1..=1)`.
384+ err. span_label ( ty. span , "the pattern must match the type" ) ;
385+ }
386+ hir:: Node :: AnonConst ( anon)
387+ if let hir:: Node :: Field ( _) = tcx. parent_hir_node ( anon. hir_id )
388+ && let ty:: Param ( _) = expected_ty. kind ( ) =>
389+ {
390+ err. note (
391+ "the type of default fields referencing type parameters can't be assumed inside \
392+ the struct defining them",
393+ ) ;
394+ }
395+ _ => { }
396+ }
397+ }
398+
277399fn infer_type_if_missing < ' tcx > ( fcx : & FnCtxt < ' _ , ' tcx > , node : Node < ' tcx > ) -> Option < Ty < ' tcx > > {
278400 let tcx = fcx. tcx ;
279401 let def_id = fcx. body_id ;
0 commit comments