|
1 | 1 | use rustc_data_structures::fx::FxIndexMap; |
2 | | -use rustc_errors::ErrorGuaranteed; |
3 | | -use rustc_hir::OpaqueTyOrigin; |
4 | | -use rustc_hir::def_id::LocalDefId; |
5 | | -use rustc_infer::infer::outlives::env::OutlivesEnvironment; |
6 | | -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; |
| 2 | +use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; |
7 | 3 | use rustc_macros::extension; |
8 | 4 | use rustc_middle::ty::{ |
9 | | - self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, |
10 | | - TypeVisitableExt, TypingMode, fold_regions, |
| 5 | + self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, |
11 | 6 | }; |
12 | 7 | use rustc_span::Span; |
13 | | -use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; |
14 | | -use rustc_trait_selection::traits::ObligationCtxt; |
| 8 | +use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid; |
15 | 9 | use tracing::{debug, instrument}; |
16 | 10 |
|
17 | 11 | use super::RegionInferenceContext; |
18 | 12 | use crate::opaque_types::ConcreteOpaqueTypes; |
19 | | -use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam}; |
| 13 | +use crate::session_diagnostics::LifetimeMismatchOpaqueParam; |
20 | 14 | use crate::universal_regions::RegionClassification; |
21 | 15 |
|
22 | 16 | impl<'tcx> RegionInferenceContext<'tcx> { |
@@ -289,156 +283,3 @@ impl<'tcx> InferCtxt<'tcx> { |
289 | 283 | definition_ty |
290 | 284 | } |
291 | 285 | } |
292 | | - |
293 | | -/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter]. |
294 | | -/// |
295 | | -/// [rustc-dev-guide chapter]: |
296 | | -/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html |
297 | | -fn check_opaque_type_parameter_valid<'tcx>( |
298 | | - infcx: &InferCtxt<'tcx>, |
299 | | - opaque_type_key: OpaqueTypeKey<'tcx>, |
300 | | - span: Span, |
301 | | -) -> Result<(), ErrorGuaranteed> { |
302 | | - let tcx = infcx.tcx; |
303 | | - let opaque_generics = tcx.generics_of(opaque_type_key.def_id); |
304 | | - let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id); |
305 | | - let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); |
306 | | - |
307 | | - for (i, arg) in opaque_type_key.iter_captured_args(tcx) { |
308 | | - let arg_is_param = match arg.unpack() { |
309 | | - GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), |
310 | | - GenericArgKind::Lifetime(lt) => { |
311 | | - matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) |
312 | | - || (lt.is_static() && opaque_env.param_equal_static(i)) |
313 | | - } |
314 | | - GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), |
315 | | - }; |
316 | | - |
317 | | - if arg_is_param { |
318 | | - // Register if the same lifetime appears multiple times in the generic args. |
319 | | - // There is an exception when the opaque type *requires* the lifetimes to be equal. |
320 | | - // See [rustc-dev-guide chapter] § "An exception to uniqueness rule". |
321 | | - let seen_where = seen_params.entry(arg).or_default(); |
322 | | - if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) { |
323 | | - seen_where.push(i); |
324 | | - } |
325 | | - } else { |
326 | | - // Prevent `fn foo() -> Foo<u32>` from being defining. |
327 | | - let opaque_param = opaque_generics.param_at(i, tcx); |
328 | | - let kind = opaque_param.kind.descr(); |
329 | | - |
330 | | - opaque_env.param_is_error(i)?; |
331 | | - |
332 | | - return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam { |
333 | | - ty: arg, |
334 | | - kind, |
335 | | - span, |
336 | | - param_span: tcx.def_span(opaque_param.def_id), |
337 | | - })); |
338 | | - } |
339 | | - } |
340 | | - |
341 | | - for (_, indices) in seen_params { |
342 | | - if indices.len() > 1 { |
343 | | - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); |
344 | | - let spans: Vec<_> = indices |
345 | | - .into_iter() |
346 | | - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) |
347 | | - .collect(); |
348 | | - #[allow(rustc::diagnostic_outside_of_impl)] |
349 | | - #[allow(rustc::untranslatable_diagnostic)] |
350 | | - return Err(infcx |
351 | | - .dcx() |
352 | | - .struct_span_err(span, "non-defining opaque type use in defining scope") |
353 | | - .with_span_note(spans, format!("{descr} used multiple times")) |
354 | | - .emit()); |
355 | | - } |
356 | | - } |
357 | | - |
358 | | - Ok(()) |
359 | | -} |
360 | | - |
361 | | -/// Computes if an opaque type requires a lifetime parameter to be equal to |
362 | | -/// another one or to the `'static` lifetime. |
363 | | -/// These requirements are derived from the explicit and implied bounds. |
364 | | -struct LazyOpaqueTyEnv<'tcx> { |
365 | | - tcx: TyCtxt<'tcx>, |
366 | | - def_id: LocalDefId, |
367 | | - |
368 | | - /// Equal parameters will have the same name. Computed Lazily. |
369 | | - /// Example: |
370 | | - /// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;` |
371 | | - /// Identity args: `['a, 'b, 'c]` |
372 | | - /// Canonical args: `['static, 'b, 'b]` |
373 | | - canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>, |
374 | | -} |
375 | | - |
376 | | -impl<'tcx> LazyOpaqueTyEnv<'tcx> { |
377 | | - fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { |
378 | | - Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() } |
379 | | - } |
380 | | - |
381 | | - fn param_equal_static(&self, param_index: usize) -> bool { |
382 | | - self.get_canonical_args()[param_index].expect_region().is_static() |
383 | | - } |
384 | | - |
385 | | - fn params_equal(&self, param1: usize, param2: usize) -> bool { |
386 | | - let canonical_args = self.get_canonical_args(); |
387 | | - canonical_args[param1] == canonical_args[param2] |
388 | | - } |
389 | | - |
390 | | - fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> { |
391 | | - self.get_canonical_args()[param_index].error_reported() |
392 | | - } |
393 | | - |
394 | | - fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> { |
395 | | - if let Some(&canonical_args) = self.canonical_args.get() { |
396 | | - return canonical_args; |
397 | | - } |
398 | | - |
399 | | - let &Self { tcx, def_id, .. } = self; |
400 | | - let origin = tcx.local_opaque_ty_origin(def_id); |
401 | | - let parent = match origin { |
402 | | - OpaqueTyOrigin::FnReturn { parent, .. } |
403 | | - | OpaqueTyOrigin::AsyncFn { parent, .. } |
404 | | - | OpaqueTyOrigin::TyAlias { parent, .. } => parent, |
405 | | - }; |
406 | | - let param_env = tcx.param_env(parent); |
407 | | - let args = GenericArgs::identity_for_item(tcx, parent).extend_to( |
408 | | - tcx, |
409 | | - def_id.to_def_id(), |
410 | | - |param, _| { |
411 | | - tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into() |
412 | | - }, |
413 | | - ); |
414 | | - |
415 | | - // FIXME(#132279): It feels wrong to use `non_body_analysis` here given that we're |
416 | | - // in a body here. |
417 | | - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); |
418 | | - let ocx = ObligationCtxt::new(&infcx); |
419 | | - |
420 | | - let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| { |
421 | | - tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds"); |
422 | | - Default::default() |
423 | | - }); |
424 | | - let outlives_env = OutlivesEnvironment::new(&infcx, parent, param_env, wf_tys); |
425 | | - |
426 | | - let mut seen = vec![tcx.lifetimes.re_static]; |
427 | | - let canonical_args = fold_regions(tcx, args, |r1, _| { |
428 | | - if r1.is_error() { |
429 | | - r1 |
430 | | - } else if let Some(&r2) = seen.iter().find(|&&r2| { |
431 | | - let free_regions = outlives_env.free_region_map(); |
432 | | - free_regions.sub_free_regions(tcx, r1, r2) |
433 | | - && free_regions.sub_free_regions(tcx, r2, r1) |
434 | | - }) { |
435 | | - r2 |
436 | | - } else { |
437 | | - seen.push(r1); |
438 | | - r1 |
439 | | - } |
440 | | - }); |
441 | | - self.canonical_args.set(canonical_args).unwrap(); |
442 | | - canonical_args |
443 | | - } |
444 | | -} |
0 commit comments