|
1 | 1 | use hir::HirId; |
2 | 2 | use rustc_abi::Primitive::Pointer; |
3 | 3 | use rustc_abi::VariantIdx; |
| 4 | +use rustc_data_structures::fx::FxHashSet; |
4 | 5 | use rustc_errors::codes::*; |
5 | 6 | use rustc_errors::struct_span_code_err; |
6 | 7 | use rustc_hir as hir; |
7 | 8 | use rustc_index::Idx; |
8 | 9 | use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; |
| 10 | +use rustc_middle::ty::offload_meta::is_region_ty; |
9 | 11 | use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized}; |
10 | 12 | use rustc_span::def_id::LocalDefId; |
11 | 13 | use rustc_span::{ErrorGuaranteed, bug}; |
@@ -134,6 +136,28 @@ fn check_transmute<'tcx>( |
134 | 136 | } |
135 | 137 | } |
136 | 138 |
|
| 139 | +fn contains_nested_offload_region<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { |
| 140 | + let mut visited = FxHashSet::default(); |
| 141 | + let mut stack = vec![ty]; |
| 142 | + let mut is_root = true; |
| 143 | + |
| 144 | + while let Some(ty) = stack.pop() { |
| 145 | + if !is_root && is_region_ty(tcx, ty) { |
| 146 | + return true; |
| 147 | + } |
| 148 | + is_root = false; |
| 149 | + |
| 150 | + if let ty::Adt(def, args) = *ty.kind() |
| 151 | + && visited.insert(def.did()) |
| 152 | + { |
| 153 | + stack.extend(def.all_fields().map(|field| field.ty(tcx, args).skip_norm_wip())); |
| 154 | + } |
| 155 | + stack.extend(ty.walk().skip(1).filter_map(|arg| arg.as_type())); |
| 156 | + } |
| 157 | + |
| 158 | + false |
| 159 | +} |
| 160 | + |
137 | 161 | fn check_offload<'tcx>( |
138 | 162 | tcx: TyCtxt<'tcx>, |
139 | 163 | typing_env: ty::TypingEnv<'tcx>, |
@@ -205,7 +229,23 @@ fn check_offload<'tcx>( |
205 | 229 | { |
206 | 230 | let norm_input_ty = normalize(input_ty); |
207 | 231 | let norm_arg_ty = normalize(arg_ty); |
208 | | - if norm_input_ty != norm_arg_ty { |
| 232 | + |
| 233 | + if contains_nested_offload_region(tcx, norm_input_ty) |
| 234 | + || contains_nested_offload_region(tcx, norm_arg_ty) |
| 235 | + { |
| 236 | + let guar = tcx |
| 237 | + .sess |
| 238 | + .dcx() |
| 239 | + .struct_span_err( |
| 240 | + span, |
| 241 | + format!( |
| 242 | + "offload kernel argument {i} contains a `Region` nested inside another \ |
| 243 | + type. Pass the `Region` by value so it can be mapped like a slice" |
| 244 | + ), |
| 245 | + ) |
| 246 | + .emit_err(); |
| 247 | + result = Err(guar); |
| 248 | + } else if norm_input_ty != norm_arg_ty { |
209 | 249 | let guar = tcx |
210 | 250 | .sess |
211 | 251 | .dcx() |
|
0 commit comments