Skip to content

Commit 1218cb2

Browse files
authored
Warn if the shadow will have internal immutability (#103)
* Warn if the shadow will have internal immutability * improve error msg
1 parent eab555d commit 1218cb2

File tree

5 files changed

+75
-15
lines changed

5 files changed

+75
-15
lines changed

compiler/rustc_codegen_llvm/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
9393
_ => continue,
9494
};
9595
let fn_ty = inst.ty(tcx, ParamEnv::empty());
96-
let _fnc_tree = fnc_typetrees(tcx, fn_ty, &mut vec![]);
96+
let _fnc_tree = fnc_typetrees(tcx, fn_ty, &mut vec![], None);
9797
//trace!("codegen_module: predefine fn {}", inst);
9898
//trace!("{} \n {:?} \n {:?}", inst, fn_ty, _fnc_tree);
9999
// Manuel: TODO

compiler/rustc_middle/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
middle_adjust_for_foreign_abi_error =
22
target architecture {$arch} does not support `extern {$abi}` ABI
33
4+
middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} is unsafe
5+
46
middle_assert_async_resume_after_panic = `async fn` resumed after panicking
57
68
middle_assert_async_resume_after_return = `async fn` resumed after completion

compiler/rustc_middle/src/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ pub struct DropCheckOverflow<'tcx> {
1717
pub overflow_ty: Ty<'tcx>,
1818
}
1919

20+
#[derive(Diagnostic)]
21+
#[diag(middle_autodiff_unsafe_inner_const_ref)]
22+
pub struct AutodiffUnsafeInnerConstRef {
23+
#[primary_span]
24+
pub span: Span,
25+
pub ty: String,
26+
}
27+
2028
#[derive(Diagnostic)]
2129
#[diag(middle_opaque_hidden_type_mismatch)]
2230
pub struct OpaqueHiddenTypeMismatch<'tcx> {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub use self::AssocItemContainer::*;
2121
pub use self::BorrowKind::*;
2222
pub use self::IntVarValue::*;
2323
pub use self::Variance::*;
24-
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason, UnsupportedUnion};
24+
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason, UnsupportedUnion, AutodiffUnsafeInnerConstRef};
2525
use crate::metadata::ModChild;
2626
use crate::middle::privacy::EffectiveVisibilities;
2727
use crate::mir::{Body, CoroutineLayout};
@@ -105,6 +105,7 @@ pub use self::typeck_results::{
105105
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity,
106106
TypeckResults, UserType, UserTypeAnnotationIndex,
107107
};
108+
use crate::query::Key;
108109

109110
pub mod _match;
110111
pub mod abstract_const;
@@ -2722,14 +2723,25 @@ mod size_asserts {
27222723

27232724
pub fn typetree_from<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> TypeTree {
27242725
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);
27262727
let tt = Type { offset: -1, kind: Kind::Pointer, size: 8, child: ty };
27272728
return TypeTree(vec![tt]);
27282729
}
27292730

27302731
use rustc_ast::expand::autodiff_attrs::DiffActivity;
27312732

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 {
27332745
if !fn_ty.is_fn() {
27342746
return FncTree { args: vec![], ret: TypeTree::new() };
27352747
}
@@ -2747,6 +2759,19 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<Diff
27472759
let mut visited = vec![];
27482760
let mut args = vec![];
27492761
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+
27502775
visited.clear();
27512776
if ty.is_unsafe_ptr() || ty.is_ref() || ty.is_box() {
27522777
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
27552780
let inner_ty = ty.builtin_deref(true).unwrap().ty;
27562781
if inner_ty.is_slice() {
27572782
// 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);
27592784
let tt = Type { offset: -1, kind: Kind::Pointer, size: 8, child };
27602785
args.push(TypeTree(vec![tt]));
27612786
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
27792804
continue;
27802805
}
27812806
}
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);
27832808
args.push(arg_tt);
27842809
}
27852810

@@ -2792,12 +2817,12 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec<Diff
27922817
}
27932818

27942819
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);
27962821

27972822
FncTree { args, ret }
27982823
}
27992824

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 {
28012826
if depth > 20 {
28022827
trace!("depth > 20 for ty: {}", &ty);
28032828
}
@@ -2812,9 +2837,33 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
28122837
if ty.is_fn_ptr() {
28132838
unimplemented!("what to do whith fn ptr?");
28142839
}
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+
28162865
//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);
28182867
let tt = Type { offset: -1, kind: Kind::Pointer, size: 8, child };
28192868
visited.pop();
28202869
return TypeTree(vec![tt]);
@@ -2884,7 +2933,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
28842933
}
28852934

28862935
//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;
28882937

28892938
for c in &mut child {
28902939
if c.offset == -1 {
@@ -2916,7 +2965,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
29162965
trace!("simd");
29172966
let (_size, inner_ty) = ty.simd_size_and_type(tcx);
29182967
//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);
29202969
//let tt = TypeTree(
29212970
// std::iter::repeat(subtt)
29222971
// .take(*count as usize)
@@ -2944,7 +2993,7 @@ pub fn typetree_from_ty<'a>(ty: Ty<'a>, tcx: TyCtxt<'a>, depth: usize, safety: b
29442993
}
29452994
let sub_ty = ty.builtin_index().unwrap();
29462995
//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);
29482997

29492998
// calculate size of subtree
29502999
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
29653014
if ty.is_slice() {
29663015
let sub_ty = ty.builtin_index().unwrap();
29673016
//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);
29693018

29703019
visited.pop();
29713020
return subtt;

compiler/rustc_monomorphize/src/partitioning.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,8 @@ fn collect_and_partition_mono_items(
12021202
println!("source_id: {:?}", inst.def_id());
12031203
let fn_ty = inst.ty(tcx, ParamEnv::empty());
12041204
assert!(fn_ty.is_fn());
1205-
let fnc_tree = fnc_typetrees(tcx, fn_ty, &mut input_activities);
1205+
let span = tcx.def_span(inst.def_id());
1206+
let fnc_tree = fnc_typetrees(tcx, fn_ty, &mut input_activities, Some(span));
12061207
let (inputs, output) = (fnc_tree.args, fnc_tree.ret);
12071208
//check_types(inst.ty(tcx, ParamEnv::empty()), tcx, &target_attrs.input_activity);
12081209
let symb = symbol_name_for_instance_in_crate(tcx, inst.clone(), LOCAL_CRATE);

0 commit comments

Comments
 (0)