9
9
// except according to those terms.
10
10
11
11
use hir:: def_id:: DefId ;
12
- use ty:: { self , TyCtxt , layout } ;
12
+ use ty;
13
13
use ty:: subst:: Substs ;
14
+ use ty:: maps:: TyCtxtAt ;
14
15
use mir:: interpret:: ConstValue ;
15
16
use errors:: DiagnosticBuilder ;
16
17
17
18
use graphviz:: IntoCow ;
18
19
use syntax_pos:: Span ;
20
+ use syntax:: ast;
19
21
20
22
use std:: borrow:: Cow ;
21
23
use rustc_data_structures:: sync:: Lrc ;
@@ -28,30 +30,26 @@ pub enum ConstVal<'tcx> {
28
30
Value ( ConstValue < ' tcx > ) ,
29
31
}
30
32
31
- #[ derive( Clone , Debug ) ]
33
+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
32
34
pub struct ConstEvalErr < ' tcx > {
33
35
pub span : Span ,
34
36
pub kind : Lrc < ErrKind < ' tcx > > ,
35
37
}
36
38
37
- #[ derive( Clone , Debug ) ]
39
+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
38
40
pub enum ErrKind < ' tcx > {
39
41
40
- NonConstPath ,
41
- UnimplementedConstVal ( & ' static str ) ,
42
- IndexOutOfBounds { len : u64 , index : u64 } ,
43
-
44
- LayoutError ( layout:: LayoutError < ' tcx > ) ,
45
-
42
+ CouldNotResolve ,
46
43
TypeckError ,
47
44
CheckMatchError ,
48
45
Miri ( :: mir:: interpret:: EvalError < ' tcx > , Vec < FrameInfo > ) ,
49
46
}
50
47
51
- #[ derive( Clone , Debug ) ]
48
+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
52
49
pub struct FrameInfo {
53
50
pub span : Span ,
54
51
pub location : String ,
52
+ pub lint_root : Option < ast:: NodeId > ,
55
53
}
56
54
57
55
#[ derive( Clone , Debug ) ]
@@ -83,81 +81,98 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
83
81
}
84
82
85
83
match * self . kind {
86
- NonConstPath => simple ! ( "non-constant path in constant expression" ) ,
87
- UnimplementedConstVal ( what) =>
88
- simple ! ( "unimplemented constant expression: {}" , what) ,
89
- IndexOutOfBounds { len, index } => {
90
- simple ! ( "index out of bounds: the len is {} but the index is {}" ,
91
- len, index)
92
- }
93
-
94
- LayoutError ( ref err) => Simple ( err. to_string ( ) . into_cow ( ) ) ,
95
-
84
+ CouldNotResolve => simple ! ( "could not resolve" ) ,
96
85
TypeckError => simple ! ( "type-checking failed" ) ,
97
86
CheckMatchError => simple ! ( "match-checking failed" ) ,
98
87
Miri ( ref err, ref trace) => Backtrace ( err, trace) ,
99
88
}
100
89
}
101
90
102
91
pub fn struct_error ( & self ,
103
- tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
104
- primary_span : Span ,
105
- primary_kind : & str )
106
- -> DiagnosticBuilder < ' gcx >
92
+ tcx : TyCtxtAt < ' a , ' gcx , ' tcx > ,
93
+ message : & str )
94
+ -> Option < DiagnosticBuilder < ' tcx > >
107
95
{
108
- let mut diag = struct_error ( tcx, self . span , "constant evaluation error" ) ;
109
- self . note ( tcx, primary_span, primary_kind, & mut diag) ;
110
- diag
96
+ self . struct_generic ( tcx, message, None , true )
111
97
}
112
98
113
- pub fn note ( & self ,
114
- _tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
115
- primary_span : Span ,
116
- primary_kind : & str ,
117
- diag : & mut DiagnosticBuilder )
118
- {
119
- match self . description ( ) {
120
- ConstEvalErrDescription :: Simple ( message) => {
121
- diag. span_label ( self . span , message) ;
122
- }
123
- ConstEvalErrDescription :: Backtrace ( miri, frames) => {
124
- diag. span_label ( self . span , format ! ( "{}" , miri) ) ;
125
- for frame in frames {
126
- diag. span_label ( frame. span , format ! ( "inside call to `{}`" , frame. location) ) ;
127
- }
128
- }
99
+ pub fn report_as_error ( & self ,
100
+ tcx : TyCtxtAt < ' a , ' gcx , ' tcx > ,
101
+ message : & str
102
+ ) {
103
+ let err = self . struct_generic ( tcx, message, None , true ) ;
104
+ if let Some ( mut err) = err {
105
+ err. emit ( ) ;
129
106
}
107
+ }
130
108
131
- if !primary_span. contains ( self . span ) {
132
- diag. span_note ( primary_span,
133
- & format ! ( "for {} here" , primary_kind) ) ;
109
+ pub fn report_as_lint ( & self ,
110
+ tcx : TyCtxtAt < ' a , ' gcx , ' tcx > ,
111
+ message : & str ,
112
+ lint_root : ast:: NodeId ,
113
+ ) {
114
+ let lint = self . struct_generic (
115
+ tcx,
116
+ message,
117
+ Some ( lint_root) ,
118
+ false ,
119
+ ) ;
120
+ if let Some ( mut lint) = lint {
121
+ lint. emit ( ) ;
134
122
}
135
123
}
136
124
137
- pub fn report ( & self ,
138
- tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
139
- primary_span : Span ,
140
- primary_kind : & str )
141
- {
142
- match * self . kind {
143
- ErrKind :: TypeckError | ErrKind :: CheckMatchError => return ,
144
- ErrKind :: Miri ( ref miri, _) => {
125
+ fn struct_generic (
126
+ & self ,
127
+ tcx : TyCtxtAt < ' a , ' gcx , ' tcx > ,
128
+ message : & str ,
129
+ lint_root : Option < ast:: NodeId > ,
130
+ as_err : bool ,
131
+ ) -> Option < DiagnosticBuilder < ' tcx > > {
132
+ let ( msg, frames) : ( _ , & [ _ ] ) = match * self . kind {
133
+ ErrKind :: TypeckError | ErrKind :: CheckMatchError => return None ,
134
+ ErrKind :: Miri ( ref miri, ref frames) => {
145
135
match miri. kind {
146
136
:: mir:: interpret:: EvalErrorKind :: TypeckError |
147
- :: mir:: interpret:: EvalErrorKind :: Layout ( _) => return ,
148
- _ => { } ,
137
+ :: mir:: interpret:: EvalErrorKind :: Layout ( _) => return None ,
138
+ :: mir:: interpret:: EvalErrorKind :: ReferencedConstant ( ref inner) => {
139
+ inner. struct_generic ( tcx, "referenced constant" , lint_root, as_err) ?. emit ( ) ;
140
+ ( miri. to_string ( ) , frames)
141
+ } ,
142
+ _ => ( miri. to_string ( ) , frames) ,
149
143
}
150
144
}
151
- _ => { }
145
+ _ => ( self . description ( ) . into_oneline ( ) . to_string ( ) , & [ ] ) ,
146
+ } ;
147
+ trace ! ( "reporting const eval failure at {:?}" , self . span) ;
148
+ let mut err = if as_err {
149
+ struct_error ( tcx, message)
150
+ } else {
151
+ let node_id = frames
152
+ . iter ( )
153
+ . rev ( )
154
+ . filter_map ( |frame| frame. lint_root )
155
+ . next ( )
156
+ . or ( lint_root)
157
+ . expect ( "some part of a failing const eval must be local" ) ;
158
+ tcx. struct_span_lint_node (
159
+ :: rustc:: lint:: builtin:: CONST_ERR ,
160
+ node_id,
161
+ tcx. span ,
162
+ message,
163
+ )
164
+ } ;
165
+ err. span_label ( self . span , msg) ;
166
+ for FrameInfo { span, location, .. } in frames {
167
+ err. span_label ( * span, format ! ( "inside call to `{}`" , location) ) ;
152
168
}
153
- self . struct_error ( tcx , primary_span , primary_kind ) . emit ( ) ;
169
+ Some ( err )
154
170
}
155
171
}
156
172
157
173
pub fn struct_error < ' a , ' gcx , ' tcx > (
158
- tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
159
- span : Span ,
174
+ tcx : TyCtxtAt < ' a , ' gcx , ' tcx > ,
160
175
msg : & str ,
161
- ) -> DiagnosticBuilder < ' gcx > {
162
- struct_span_err ! ( tcx. sess, span, E0080 , "{}" , msg)
176
+ ) -> DiagnosticBuilder < ' tcx > {
177
+ struct_span_err ! ( tcx. sess, tcx . span, E0080 , "{}" , msg)
163
178
}
0 commit comments