99// except according to those terms.
1010
1111use hir:: def_id:: DefId ;
12- use ty:: { self , TyCtxt , layout } ;
12+ use ty;
1313use ty:: subst:: Substs ;
14+ use ty:: maps:: TyCtxtAt ;
1415use mir:: interpret:: ConstValue ;
1516use errors:: DiagnosticBuilder ;
1617
1718use graphviz:: IntoCow ;
1819use syntax_pos:: Span ;
20+ use syntax:: ast;
1921
2022use std:: borrow:: Cow ;
2123use rustc_data_structures:: sync:: Lrc ;
@@ -28,30 +30,26 @@ pub enum ConstVal<'tcx> {
2830 Value ( ConstValue < ' tcx > ) ,
2931}
3032
31- #[ derive( Clone , Debug ) ]
33+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
3234pub struct ConstEvalErr < ' tcx > {
3335 pub span : Span ,
3436 pub kind : Lrc < ErrKind < ' tcx > > ,
3537}
3638
37- #[ derive( Clone , Debug ) ]
39+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
3840pub enum ErrKind < ' tcx > {
3941
40- NonConstPath ,
41- UnimplementedConstVal ( & ' static str ) ,
42- IndexOutOfBounds { len : u64 , index : u64 } ,
43-
44- LayoutError ( layout:: LayoutError < ' tcx > ) ,
45-
42+ CouldNotResolve ,
4643 TypeckError ,
4744 CheckMatchError ,
4845 Miri ( :: mir:: interpret:: EvalError < ' tcx > , Vec < FrameInfo > ) ,
4946}
5047
51- #[ derive( Clone , Debug ) ]
48+ #[ derive( Clone , Debug , RustcEncodable , RustcDecodable ) ]
5249pub struct FrameInfo {
5350 pub span : Span ,
5451 pub location : String ,
52+ pub lint_root : Option < ast:: NodeId > ,
5553}
5654
5755#[ derive( Clone , Debug ) ]
@@ -83,81 +81,98 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
8381 }
8482
8583 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" ) ,
9685 TypeckError => simple ! ( "type-checking failed" ) ,
9786 CheckMatchError => simple ! ( "match-checking failed" ) ,
9887 Miri ( ref err, ref trace) => Backtrace ( err, trace) ,
9988 }
10089 }
10190
10291 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 > >
10795 {
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 )
11197 }
11298
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 ( ) ;
129106 }
107+ }
130108
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 ( ) ;
134122 }
135123 }
136124
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) => {
145135 match miri. kind {
146136 :: 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) ,
149143 }
150144 }
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) ) ;
152168 }
153- self . struct_error ( tcx , primary_span , primary_kind ) . emit ( ) ;
169+ Some ( err )
154170 }
155171}
156172
157173pub fn struct_error < ' a , ' gcx , ' tcx > (
158- tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
159- span : Span ,
174+ tcx : TyCtxtAt < ' a , ' gcx , ' tcx > ,
160175 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)
163178}
0 commit comments