diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index 587536e1f9a3b..9f248cb30682c 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -132,6 +132,10 @@ borrowck_moved_due_to_usage_in_operator = *[false] operator } +borrowck_must_define_opaque = + method must define opaque type + .label = because it shows up in the args of this method + borrowck_opaque_type_lifetime_mismatch = opaque type used twice with different lifetimes .label = lifetime `{$arg}` used here diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index d5875a226fe02..3596c8c0fb7aa 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -16,8 +16,9 @@ use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::ObligationCtxt; -use crate::session_diagnostics::LifetimeMismatchOpaqueParam; -use crate::session_diagnostics::NonGenericOpaqueTypeParam; +use crate::session_diagnostics::{ + LifetimeMismatchOpaqueParam, MustDefineOpaque, NonGenericOpaqueTypeParam, +}; use super::RegionInferenceContext; @@ -42,12 +43,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Check that all opaque types have the same region parameters if they have the same /// non-region parameters. This is necessary because within the new solver we perform various query operations /// modulo regions, and thus could unsoundly select some impls that don't hold. - fn check_unique( + fn check_unique_and_defined( &self, infcx: &InferCtxt<'tcx>, + anchor: LocalDefId, opaque_ty_decls: &FxIndexMap, OpaqueHiddenType<'tcx>>, ) { + let mut seen = FxIndexSet::default(); for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() { + seen.insert(a.def_id); for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) { if a.def_id != b.def_id { continue; @@ -78,6 +82,24 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } } + + if !infcx.tcx.is_typeck_child(anchor.to_def_id()) { + // Check that all the in-scope ATPITs are defined by the anchor + for def_id in infcx.tcx.opaque_types_defined_by(anchor) { + if seen.contains(&def_id) { + continue; + } + match infcx.tcx.opaque_type_origin(def_id) { + OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => { + infcx.dcx().emit_err(MustDefineOpaque { + span: infcx.tcx.def_span(def_id), + item_span: infcx.tcx.def_span(anchor), + }); + } + _ => {} + } + } + } } /// Resolve any opaque types that were encountered while borrow checking @@ -125,7 +147,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx: &InferCtxt<'tcx>, opaque_ty_decls: FxIndexMap, OpaqueHiddenType<'tcx>>, ) -> FxIndexMap> { - self.check_unique(infcx, &opaque_ty_decls); + self.check_unique_and_defined( + infcx, + self.universal_regions().defining_ty.def_id().expect_local(), + &opaque_ty_decls, + ); let mut result: FxIndexMap> = FxIndexMap::default(); diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 40c2ef1c91e14..09059c32941ed 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -304,6 +304,15 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { pub param_span: Span, } +#[derive(Diagnostic)] +#[diag(borrowck_must_define_opaque)] +pub(crate) struct MustDefineOpaque { + #[primary_span] + pub span: Span, + #[label] + pub item_span: Span, +} + #[derive(Diagnostic)] #[diag(borrowck_opaque_type_lifetime_mismatch)] pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> { diff --git a/tests/ui/generic-associated-types/issue-87258_a.stderr b/tests/ui/generic-associated-types/issue-87258_a.stderr index 01f2a92f94a6b..d79754ad6a561 100644 --- a/tests/ui/generic-associated-types/issue-87258_a.stderr +++ b/tests/ui/generic-associated-types/issue-87258_a.stderr @@ -1,3 +1,12 @@ +error: method must define opaque type + --> $DIR/issue-87258_a.rs:17:26 + | +LL | type FooFuture<'a> = impl Trait1; + | ^^^^^^^^^^^ +LL | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ----------------------------------- because it shows up in the args of this method + error: unconstrained opaque type --> $DIR/issue-87258_a.rs:17:26 | @@ -6,5 +15,5 @@ LL | type FooFuture<'a> = impl Trait1; | = note: `FooFuture` must be used in combination with a concrete type within the same impl -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr index 1274a8b60dea0..a02dff11c99ce 100644 --- a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr +++ b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr @@ -9,6 +9,16 @@ LL | fn bar<'a: 'a>() LL | let _: Self::Assoc<'a> = x; | ^^^^^^^^^^^^^^^ +error: method must define opaque type + --> $DIR/in-assoc-ty-early-bound2.rs:9:22 + | +LL | type Assoc<'a> = impl Sized; + | ^^^^^^^^^^ +LL | / fn bar<'a: 'a>() +LL | | where +LL | | Self::Assoc<'a>:, + | |_________________________- because it shows up in the args of this method + error: unconstrained opaque type --> $DIR/in-assoc-ty-early-bound2.rs:9:22 | @@ -17,6 +27,6 @@ LL | type Assoc<'a> = impl Sized; | = note: `Assoc` must be used in combination with a concrete type within the same impl -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0700`.