@@ -22,7 +22,7 @@ use fmt_macros::{Parser, Piece, Position};
22
22
use middle:: infer:: InferCtxt ;
23
23
use middle:: ty:: { self , AsPredicate , ReferencesError , ToPolyTraitRef , TraitRef } ;
24
24
use std:: collections:: HashMap ;
25
- use syntax:: codemap:: Span ;
25
+ use syntax:: codemap:: { DUMMY_SP , Span } ;
26
26
use syntax:: attr:: { AttributeMethods , AttrMetaMethods } ;
27
27
use util:: ppaux:: { Repr , UserString } ;
28
28
@@ -66,13 +66,20 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
66
66
}
67
67
68
68
fn 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 > {
70
71
let def_id = trait_ref. def_id ;
71
72
let mut report = None ;
72
73
ty:: each_attr ( infcx. tcx , def_id, |item| {
73
74
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 ) ;
74
82
if let Some ( ref istring) = item. value_str ( ) {
75
- let def = ty:: lookup_trait_def ( infcx. tcx , def_id) ;
76
83
let mut generic_map = def. generics . types . iter_enumerated ( )
77
84
. map ( |( param, i, gen) | {
78
85
( gen. name . as_str ( ) . to_string ( ) ,
@@ -91,20 +98,24 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
91
98
Some ( val) => Some ( val. as_slice ( ) ) ,
92
99
None => {
93
100
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 )
99
106
. as_slice ( ) ) ;
100
107
errored = true ;
101
108
None
102
109
}
103
110
} ,
104
111
_ => {
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 ( ) ) ;
108
119
errored = true ;
109
120
None
110
121
}
@@ -116,9 +127,11 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
116
127
report = Some ( err) ;
117
128
}
118
129
} 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 ( ) ) ;
122
135
}
123
136
false
124
137
} else {
@@ -154,15 +167,16 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
154
167
infcx. resolve_type_vars_if_possible ( trait_predicate) ;
155
168
if !trait_predicate. references_error ( ) {
156
169
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 ) ;
160
170
infcx. tcx . sess . span_err (
161
171
obligation. cause . span ,
162
172
format ! (
163
173
"the trait `{}` is not implemented for the type `{}`" ,
164
174
trait_ref. user_string( infcx. tcx) ,
165
175
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 ) ;
166
180
if let Some ( s) = custom_note {
167
181
infcx. tcx . sess . span_note (
168
182
obligation. cause . span ,
0 commit comments