11use rusty_common:: { HasPos , Position } ;
22
3- //
4- // ErrorEnvelope
5- //
6-
3+ /// ErrorEnvelope wraps an error with stacktrace information.
74#[ derive( Clone , Debug , PartialEq , Eq ) ]
8- pub enum ErrorEnvelope < T > {
9- NoPos ( T ) ,
10- Pos ( T , Position ) ,
11- Stacktrace ( T , Vec < Position > ) ,
12- }
13-
14- impl < T > AsRef < T > for ErrorEnvelope < T > {
15- fn as_ref ( & self ) -> & T {
16- match self {
17- Self :: NoPos ( t) | Self :: Pos ( t, _) | Self :: Stacktrace ( t, _) => t,
18- }
19- }
20- }
5+ pub struct ErrorEnvelope < T > ( T , Vec < Position > ) ;
216
227impl < T > ErrorEnvelope < T > {
23- pub fn into_err ( self ) -> T {
24- match self {
25- Self :: NoPos ( t) | Self :: Pos ( t, _) | Self :: Stacktrace ( t, _) => t,
26- }
8+ pub fn new ( err : T , pos : Position ) -> Self {
9+ Self ( err, vec ! [ pos] )
2710 }
2811
29- /// Patches the envelope with the given position.
30- /// If the object already has a position or a stacktrace,
31- /// it is returned as-is.
32- pub fn patch_pos ( self , pos : Position ) -> Self {
33- match self {
34- Self :: NoPos ( t) => Self :: Pos ( t, pos) ,
35- _ => self ,
36- }
12+ pub fn new_with_stacktrace ( err : T , stacktrace : Vec < Position > ) -> Self {
13+ Self ( err, stacktrace)
3714 }
3815
39- pub fn patch_stacktrace ( self , v_new : & mut Vec < Position > ) -> Self {
40- let mut v_old: Vec < Position > = match & self {
41- Self :: NoPos ( _) => vec ! [ ] ,
42- Self :: Pos ( _, p) => vec ! [ * p] ,
43- Self :: Stacktrace ( _, v) => v. clone ( ) ,
44- } ;
45- v_old. append ( v_new) ;
46- let body = self . into_err ( ) ;
47- if v_old. is_empty ( ) {
48- Self :: NoPos ( body)
49- } else if v_old. len ( ) == 1 {
50- Self :: Pos ( body, v_old. pop ( ) . unwrap ( ) )
16+ pub fn new_draining_stacktrace ( err : T , stacktrace : & mut Vec < Position > ) -> Self {
17+ debug_assert ! ( !stacktrace. is_empty( ) ) ;
18+ if stacktrace. len ( ) == 1 {
19+ Self :: new ( err, stacktrace. pop ( ) . unwrap ( ) )
5120 } else {
52- Self :: Stacktrace ( body, v_old)
21+ let new_stacktrace = stacktrace. drain ( 0 ..stacktrace. len ( ) ) . collect ( ) ;
22+ Self ( err, new_stacktrace)
5323 }
5424 }
55- }
5625
57- //
58- // result.with_err_no_pos()
59- //
60-
61- pub trait WithErrNoPos < TResult > {
62- fn with_err_no_pos ( self ) -> TResult ;
63- }
26+ pub fn err ( & self ) -> & T {
27+ & self . 0
28+ }
6429
65- impl < T , E > WithErrNoPos < Result < T , ErrorEnvelope < E > > > for Result < T , E > {
66- fn with_err_no_pos ( self ) -> Result < T , ErrorEnvelope < E > > {
67- self . map_err ( |e| ErrorEnvelope :: NoPos ( e) )
30+ pub fn appen_draining_stacktrace ( self , stacktrace : & mut Vec < Position > ) -> Self {
31+ let Self ( err, mut old_stacktrace) = self ;
32+ old_stacktrace. append ( stacktrace) ;
33+ Self ( err, old_stacktrace)
6834 }
6935}
7036
@@ -78,20 +44,24 @@ pub trait WithErrAt<Pos, TResult> {
7844
7945impl < Pos : HasPos , T , E > WithErrAt < & Pos , Result < T , ErrorEnvelope < E > > > for Result < T , E > {
8046 fn with_err_at ( self , p : & Pos ) -> Result < T , ErrorEnvelope < E > > {
81- self . map_err ( |e| ErrorEnvelope :: Pos ( e, p. pos ( ) ) )
47+ self . map_err ( |e| ErrorEnvelope :: new ( e, p. pos ( ) ) )
8248 }
8349}
8450
85- //
86- // result.patch_err_pos()
87- //
51+ pub trait WithStacktrace < O = Self > {
52+ /// Adds the given stacktrace to the error.
53+ /// The given stacktrace is emptied, to avoid adding the same items twice.
54+ fn with_stacktrace ( self , stacktrace : & mut Vec < Position > ) -> O ;
55+ }
8856
89- pub trait PatchErrPos < Pos , TResult > {
90- fn patch_err_pos ( self , p : Pos ) -> TResult ;
57+ impl < T > WithStacktrace for ErrorEnvelope < T > {
58+ fn with_stacktrace ( self , stacktrace : & mut Vec < Position > ) -> Self {
59+ self . appen_draining_stacktrace ( stacktrace)
60+ }
9161}
9262
93- impl < Pos : HasPos , T , E > PatchErrPos < & Pos , Self > for Result < T , ErrorEnvelope < E > > {
94- fn patch_err_pos ( self , p : & Pos ) -> Self {
95- self . map_err ( |e| e . patch_pos ( p . pos ( ) ) )
63+ impl < T , E > WithStacktrace < Result < T , ErrorEnvelope < E > > > for Result < T , E > {
64+ fn with_stacktrace ( self , stacktrace : & mut Vec < Position > ) -> Result < T , ErrorEnvelope < E > > {
65+ self . map_err ( |err| ErrorEnvelope :: new_draining_stacktrace ( err , stacktrace ) )
9666 }
9767}
0 commit comments