diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 302936ad1a1..f0b5f99cc9f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1696,7 +1696,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); return None; }; - Some(did) + Some((self.lower_span(path.span), did)) }); let define_opaque = self.arena.alloc_from_iter(define_opaque); self.define_opaque = Some(define_opaque); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e42a4b460fe..e5569458dbd 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -99,7 +99,7 @@ struct LoweringContext<'a, 'hir> { /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// `#[define_opaque]` attributes - define_opaque: Option<&'hir [LocalDefId]>, + define_opaque: Option<&'hir [(Span, LocalDefId)]>, /// Attributes inside the owner being lowered. attrs: SortedMap, /// Collect items that were created by lowering the current owner. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1c54b99b12f..53f0194091c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1308,7 +1308,7 @@ impl Attribute { pub struct AttributeMap<'tcx> { pub map: SortedMap, /// Preprocessed `#[define_opaque]` attribute. - pub define_opaque: Option<&'tcx [LocalDefId]>, + pub define_opaque: Option<&'tcx [(Span, LocalDefId)]>, // Only present when the crate hash is needed. pub opt_hash: Option, } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 2d590dfdd14..a107925fb18 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -190,11 +190,14 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { let Some(defines) = self.tcx.hir_attrs(hir_id.owner).define_opaque else { return; }; - for &define in defines { + for &(span, define) in defines { trace!(?define); let mode = std::mem::replace(&mut self.mode, CollectionMode::Taits); - // TODO: check that opaque types were introduced and error otherwise (also add tests) + let n = self.opaques.len(); super::sig_types::walk_types(self.tcx, define, self); + if n == self.opaques.len() { + self.tcx.dcx().span_err(span, "item does not contain any opaque types"); + } self.mode = mode; } // Allow using `#[define_opaque]` on assoc methods and type aliases to override the default collection mode in diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs index d995e785cc8..4b60bad5c03 100644 --- a/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs +++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs @@ -1,8 +1,7 @@ -//@ check-pass - #![feature(type_alias_impl_trait)] type Thing = (); #[define_opaque(Thing)] +//~^ ERROR item does not contain any opaque types fn main() {} diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr new file mode 100644 index 00000000000..66ae3a43b95 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr @@ -0,0 +1,8 @@ +error: item does not contain any opaque types + --> $DIR/no_opaque.rs:5:17 + | +LL | #[define_opaque(Thing)] + | ^^^^^ + +error: aborting due to 1 previous error +