@@ -21,7 +21,7 @@ pub use self::AssocItemContainer::*;
21
21
pub use self :: BorrowKind :: * ;
22
22
pub use self :: IntVarValue :: * ;
23
23
pub use self :: Variance :: * ;
24
- use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason , UnsupportedUnion } ;
24
+ use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason , UnsupportedUnion , AutodiffUnsafeInnerConstRef } ;
25
25
use crate :: metadata:: ModChild ;
26
26
use crate :: middle:: privacy:: EffectiveVisibilities ;
27
27
use crate :: mir:: { Body , CoroutineLayout } ;
@@ -105,6 +105,7 @@ pub use self::typeck_results::{
105
105
CanonicalUserType , CanonicalUserTypeAnnotation , CanonicalUserTypeAnnotations , IsIdentity ,
106
106
TypeckResults , UserType , UserTypeAnnotationIndex ,
107
107
} ;
108
+ use crate :: query:: Key ;
108
109
109
110
pub mod _match;
110
111
pub mod abstract_const;
@@ -2722,14 +2723,25 @@ mod size_asserts {
2722
2723
2723
2724
pub fn typetree_from < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> TypeTree {
2724
2725
let mut visited = vec ! [ ] ;
2725
- let ty = typetree_from_ty ( ty, tcx, 0 , false , & mut visited) ;
2726
+ let ty = typetree_from_ty ( ty, tcx, 0 , false , & mut visited, None ) ;
2726
2727
let tt = Type { offset : -1 , kind : Kind :: Pointer , size : 8 , child : ty } ;
2727
2728
return TypeTree ( vec ! [ tt] ) ;
2728
2729
}
2729
2730
2730
2731
use rustc_ast:: expand:: autodiff_attrs:: DiffActivity ;
2731
2732
2732
- pub fn fnc_typetrees < ' tcx > ( tcx : TyCtxt < ' tcx > , fn_ty : Ty < ' tcx > , da : & mut Vec < DiffActivity > ) -> FncTree {
2733
+ // This function combines three tasks. To avoid traversing each type 3x, we combine them.
2734
+ // 1. Create a TypeTree from a Ty. This is the main task.
2735
+ // 2. IFF da is not empty, we also want to adjust DiffActivity to account for future MIR->LLVM
2736
+ // lowering. E.g. fat ptr are going to introduce an extra int.
2737
+ // 3. IFF da is not empty, we are creating TT for a function directly differentiated (has an
2738
+ // autodiff macro on top). Here we want to make sure that shadows are mutable internally.
2739
+ // We know the outermost ref/ptr indirection is mutability - we generate it like that.
2740
+ // We now have to make sure that inner ptr/ref are mutable too, or issue a warning.
2741
+ // Not an error, becaues it only causes issues if they are actually read, which we don't check
2742
+ // yet. We should add such analysis to relibably either issue an error or accept without warning.
2743
+ // If there only were some reasearch to do that...
2744
+ pub fn fnc_typetrees < ' tcx > ( tcx : TyCtxt < ' tcx > , fn_ty : Ty < ' tcx > , da : & mut Vec < DiffActivity > , span : Option < Span > ) -> FncTree {
2733
2745
if !fn_ty. is_fn ( ) {
2734
2746
return FncTree { args : vec ! [ ] , ret : TypeTree :: new ( ) } ;
2735
2747
}
@@ -2747,6 +2759,19 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<Diff
2747
2759
let mut visited = vec ! [ ] ;
2748
2760
let mut args = vec ! [ ] ;
2749
2761
for ( i, ty) in x. inputs ( ) . iter ( ) . enumerate ( ) {
2762
+ // We care about safety checks, if an argument get's duplicated and we write into the
2763
+ // shadow. That's equivalent to Duplicated or DuplicatedOnly.
2764
+ let safety = if !da. is_empty ( ) {
2765
+ // If we have Activities, we also have spans
2766
+ assert ! ( span. is_some( ) ) ;
2767
+ match da[ i] {
2768
+ DiffActivity :: DuplicatedOnly | DiffActivity :: Duplicated => true ,
2769
+ _ => false ,
2770
+ }
2771
+ } else {
2772
+ false
2773
+ } ;
2774
+
2750
2775
visited. clear ( ) ;
2751
2776
if ty. is_unsafe_ptr ( ) || ty. is_ref ( ) || ty. is_box ( ) {
2752
2777
if ty. is_fn_ptr ( ) {
@@ -2755,7 +2780,7 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<Diff
2755
2780
let inner_ty = ty. builtin_deref ( true ) . unwrap ( ) . ty ;
2756
2781
if inner_ty. is_slice ( ) {
2757
2782
// We know that the lenght will be passed as extra arg.
2758
- let child = typetree_from_ty ( inner_ty, tcx, 0 , false , & mut visited) ;
2783
+ let child = typetree_from_ty ( inner_ty, tcx, 1 , safety , & mut visited, span ) ;
2759
2784
let tt = Type { offset : -1 , kind : Kind :: Pointer , size : 8 , child } ;
2760
2785
args. push ( TypeTree ( vec ! [ tt] ) ) ;
2761
2786
let i64_tt = Type { offset : -1 , kind : Kind :: Integer , size : 8 , child : TypeTree :: new ( ) } ;
@@ -2779,7 +2804,7 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<Diff
2779
2804
continue ;
2780
2805
}
2781
2806
}
2782
- let arg_tt = typetree_from_ty ( * ty, tcx, 0 , false , & mut visited) ;
2807
+ let arg_tt = typetree_from_ty ( * ty, tcx, 0 , safety , & mut visited, span ) ;
2783
2808
args. push ( arg_tt) ;
2784
2809
}
2785
2810
@@ -2792,12 +2817,12 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<Diff
2792
2817
}
2793
2818
2794
2819
visited. clear ( ) ;
2795
- let ret = typetree_from_ty ( x. output ( ) , tcx, 0 , false , & mut visited) ;
2820
+ let ret = typetree_from_ty ( x. output ( ) , tcx, 0 , false , & mut visited, span ) ;
2796
2821
2797
2822
FncTree { args, ret }
2798
2823
}
2799
2824
2800
- pub fn typetree_from_ty < ' a > ( ty : Ty < ' a > , tcx : TyCtxt < ' a > , depth : usize , safety : bool , visited : & mut Vec < Ty < ' a > > ) -> TypeTree {
2825
+ fn typetree_from_ty < ' a > ( ty : Ty < ' a > , tcx : TyCtxt < ' a > , depth : usize , safety : bool , visited : & mut Vec < Ty < ' a > > , span : Option < Span > ) -> TypeTree {
2801
2826
if depth > 20 {
2802
2827
trace ! ( "depth > 20 for ty: {}" , & ty) ;
2803
2828
}
@@ -2812,9 +2837,33 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
2812
2837
if ty. is_fn_ptr ( ) {
2813
2838
unimplemented ! ( "what to do whith fn ptr?" ) ;
2814
2839
}
2815
- let inner_ty = ty. builtin_deref ( true ) . unwrap ( ) . ty ;
2840
+
2841
+ let inner_ty_and_mut = ty. builtin_deref ( true ) . unwrap ( ) ;
2842
+ let is_mut = inner_ty_and_mut. mutbl == hir:: Mutability :: Mut ;
2843
+ let inner_ty = inner_ty_and_mut. ty ;
2844
+
2845
+ // Now account for inner mutability.
2846
+ if !is_mut && depth > 0 && safety {
2847
+ let ptr_ty: String = if ty. is_ref ( ) {
2848
+ "ref"
2849
+ } else if ty. is_unsafe_ptr ( ) {
2850
+ "ptr"
2851
+ } else {
2852
+ assert ! ( ty. is_box( ) ) ;
2853
+ "box"
2854
+ } . to_string ( ) ;
2855
+
2856
+ // If we have mutability, we also have a span
2857
+ assert ! ( span. is_some( ) ) ;
2858
+ let span = span. unwrap ( ) ;
2859
+
2860
+ tcx. sess
2861
+ . dcx ( )
2862
+ . emit_warning ( AutodiffUnsafeInnerConstRef { span, ty : ptr_ty} ) ;
2863
+ }
2864
+
2816
2865
//visited.push(inner_ty);
2817
- let child = typetree_from_ty ( inner_ty, tcx, depth + 1 , safety, visited) ;
2866
+ let child = typetree_from_ty ( inner_ty, tcx, depth + 1 , safety, visited, span ) ;
2818
2867
let tt = Type { offset : -1 , kind : Kind :: Pointer , size : 8 , child } ;
2819
2868
visited. pop ( ) ;
2820
2869
return TypeTree ( vec ! [ tt] ) ;
@@ -2884,7 +2933,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
2884
2933
}
2885
2934
2886
2935
//visited.push(field_ty);
2887
- let mut child = typetree_from_ty ( field_ty, tcx, depth + 1 , safety, visited) . 0 ;
2936
+ let mut child = typetree_from_ty ( field_ty, tcx, depth + 1 , safety, visited, span ) . 0 ;
2888
2937
2889
2938
for c in & mut child {
2890
2939
if c. offset == -1 {
@@ -2916,7 +2965,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
2916
2965
trace ! ( "simd" ) ;
2917
2966
let ( _size, inner_ty) = ty. simd_size_and_type ( tcx) ;
2918
2967
//visited.push(inner_ty);
2919
- let _sub_tt = typetree_from_ty ( inner_ty, tcx, depth + 1 , safety, visited) ;
2968
+ let _sub_tt = typetree_from_ty ( inner_ty, tcx, depth + 1 , safety, visited, span ) ;
2920
2969
//let tt = TypeTree(
2921
2970
// std::iter::repeat(subtt)
2922
2971
// .take(*count as usize)
@@ -2944,7 +2993,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
2944
2993
}
2945
2994
let sub_ty = ty. builtin_index ( ) . unwrap ( ) ;
2946
2995
//visited.push(sub_ty);
2947
- let subtt = typetree_from_ty ( sub_ty, tcx, depth + 1 , safety, visited) ;
2996
+ let subtt = typetree_from_ty ( sub_ty, tcx, depth + 1 , safety, visited, span ) ;
2948
2997
2949
2998
// calculate size of subtree
2950
2999
let param_env_and = ParamEnvAnd { param_env : ParamEnv :: empty ( ) , value : sub_ty } ;
@@ -2965,7 +3014,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
2965
3014
if ty. is_slice ( ) {
2966
3015
let sub_ty = ty. builtin_index ( ) . unwrap ( ) ;
2967
3016
//visited.push(sub_ty);
2968
- let subtt = typetree_from_ty ( sub_ty, tcx, depth + 1 , safety, visited) ;
3017
+ let subtt = typetree_from_ty ( sub_ty, tcx, depth + 1 , safety, visited, span ) ;
2969
3018
2970
3019
visited. pop ( ) ;
2971
3020
return subtt;
0 commit comments