@@ -22,7 +22,7 @@ use fmt_macros::{Parser, Piece, Position};
2222use middle:: infer:: InferCtxt ;
2323use middle:: ty:: { self , AsPredicate , ReferencesError , ToPolyTraitRef , TraitRef } ;
2424use std:: collections:: HashMap ;
25- use syntax:: codemap:: Span ;
25+ use syntax:: codemap:: { DUMMY_SP , Span } ;
2626use syntax:: attr:: { AttributeMethods , AttrMetaMethods } ;
2727use util:: ppaux:: { Repr , UserString } ;
2828
@@ -66,13 +66,20 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
6666}
6767
6868fn report_on_unimplemented < ' a , ' tcx > ( infcx : & InferCtxt < ' a , ' tcx > ,
69- trait_ref : & TraitRef < ' tcx > ) -> Option < String > {
69+ trait_ref : & TraitRef < ' tcx > ,
70+ span : Span ) -> Option < String > {
7071 let def_id = trait_ref. def_id ;
7172 let mut report = None ;
7273 ty:: each_attr ( infcx. tcx , def_id, |item| {
7374 if item. check_name ( "on_unimplemented" ) {
75+ let err_sp = if item. meta ( ) . span == DUMMY_SP {
76+ span
77+ } else {
78+ item. meta ( ) . span
79+ } ;
80+ let def = ty:: lookup_trait_def ( infcx. tcx , def_id) ;
81+ let trait_str = def. trait_ref . user_string ( infcx. tcx ) ;
7482 if let Some ( ref istring) = item. value_str ( ) {
75- let def = ty:: lookup_trait_def ( infcx. tcx , def_id) ;
7683 let mut generic_map = def. generics . types . iter_enumerated ( )
7784 . map ( |( param, i, gen) | {
7885 ( gen. name . as_str ( ) . to_string ( ) ,
@@ -91,20 +98,24 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
9198 Some ( val) => Some ( val. as_slice ( ) ) ,
9299 None => {
93100 infcx. tcx . sess
94- . span_err ( item . meta ( ) . span ,
95- format ! ( "there is no type parameter \
96- {} on trait {}" ,
97- s , def . trait_ref
98- . user_string ( infcx . tcx ) )
101+ . span_err ( err_sp ,
102+ format ! ( "the #[on_unimplemented] attribute on \
103+ trait definition for {} refers to \
104+ non-existent type parameter {}" ,
105+ trait_str , s )
99106 . as_slice ( ) ) ;
100107 errored = true ;
101108 None
102109 }
103110 } ,
104111 _ => {
105- infcx. tcx . sess . span_err ( item. meta ( ) . span ,
106- "only named substitution \
107- parameters are allowed") ;
112+ infcx. tcx . sess
113+ . span_err ( err_sp,
114+ format ! ( "the #[on_unimplemented] attribute on \
115+ trait definition for {} must have named \
116+ format arguments, \
117+ eg `#[on_unimplemented = \" foo {{T}}\" ]`",
118+ trait_str) . as_slice ( ) ) ;
108119 errored = true ;
109120 None
110121 }
@@ -116,9 +127,11 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
116127 report = Some ( err) ;
117128 }
118129 } else {
119- infcx. tcx . sess . span_err ( item. meta ( ) . span ,
120- "this attribute must have a value, \
121- eg `#[on_unimplemented = \" foo\" ]`")
130+ infcx. tcx . sess . span_err ( err_sp,
131+ format ! ( "the #[on_unimplemented] attribute on \
132+ trait definition for {} must have a value, \
133+ eg `#[on_unimplemented = \" foo\" ]`",
134+ trait_str) . as_slice ( ) ) ;
122135 }
123136 false
124137 } else {
@@ -154,15 +167,16 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
154167 infcx. resolve_type_vars_if_possible ( trait_predicate) ;
155168 if !trait_predicate. references_error ( ) {
156169 let trait_ref = trait_predicate. to_poly_trait_ref ( ) ;
157- // Check if it has a custom "#[on_unimplemented]" error message,
158- // report with that message if it does
159- let custom_note = report_on_unimplemented ( infcx, & * trait_ref. 0 ) ;
160170 infcx. tcx . sess . span_err (
161171 obligation. cause . span ,
162172 format ! (
163173 "the trait `{}` is not implemented for the type `{}`" ,
164174 trait_ref. user_string( infcx. tcx) ,
165175 trait_ref. self_ty( ) . user_string( infcx. tcx) ) . as_slice ( ) ) ;
176+ // Check if it has a custom "#[on_unimplemented]" error message,
177+ // report with that message if it does
178+ let custom_note = report_on_unimplemented ( infcx, & * trait_ref. 0 ,
179+ obligation. cause . span ) ;
166180 if let Some ( s) = custom_note {
167181 infcx. tcx . sess . span_note (
168182 obligation. cause . span ,
0 commit comments