Auto merge of #128440 - oli-obk:defines, r=lcnr

Add `#[define_opaques]` attribute and require it for all type-alias-impl-trait sites that register a hidden type

Instead of relying on the signature of items to decide whether they are constraining an opaque type, the opaque types that the item constrains must be explicitly listed.

A previous version of this PR used an actual attribute, but had to keep the resolved `DefId`s in a side table.

Now we just lower to fields in the AST that have no surface syntax, instead a builtin attribute macro fills in those fields where applicable.

Note that for convenience referencing opaque types in associated types from associated methods on the same impl will not require an attribute. If that causes problems `#[defines()]` can be used to overwrite the default of searching for opaques in the signature.

One wart of this design is that closures and static items do not have generics. So since I stored the opaques in the generics of functions, consts and methods, I would need to add a custom field to closures and statics to track this information. During a T-types discussion we decided to just not do this for now.

fixes #131298
This commit is contained in:
bors 2025-03-11 18:13:31 +00:00
commit 6650252439
666 changed files with 3025 additions and 2582 deletions

View file

@ -4529,6 +4529,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"itertools", "itertools",
"rustc_abi", "rustc_abi",
"rustc_attr_parsing",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
"rustc_fluent_macro", "rustc_fluent_macro",

View file

@ -3466,6 +3466,7 @@ pub struct Fn {
pub generics: Generics, pub generics: Generics,
pub sig: FnSig, pub sig: FnSig,
pub contract: Option<P<FnContract>>, pub contract: Option<P<FnContract>>,
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
pub body: Option<P<Block>>, pub body: Option<P<Block>>,
} }
@ -3763,7 +3764,7 @@ mod size_asserts {
static_assert_size!(Block, 32); static_assert_size!(Block, 32);
static_assert_size!(Expr, 72); static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40); static_assert_size!(ExprKind, 40);
static_assert_size!(Fn, 168); static_assert_size!(Fn, 176);
static_assert_size!(ForeignItem, 88); static_assert_size!(ForeignItem, 88);
static_assert_size!(ForeignItemKind, 16); static_assert_size!(ForeignItemKind, 16);
static_assert_size!(GenericArg, 24); static_assert_size!(GenericArg, 24);

View file

@ -973,7 +973,14 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
_ctxt, _ctxt,
_ident, _ident,
_vis, _vis,
Fn { defaultness, generics, contract, body, sig: FnSig { header, decl, span } }, Fn {
defaultness,
generics,
contract,
body,
sig: FnSig { header, decl, span },
define_opaque,
},
) => { ) => {
// Identifier and visibility are visited as a part of the item. // Identifier and visibility are visited as a part of the item.
visit_defaultness(vis, defaultness); visit_defaultness(vis, defaultness);
@ -987,6 +994,11 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
vis.visit_block(body); vis.visit_block(body);
} }
vis.visit_span(span); vis.visit_span(span);
for (id, path) in define_opaque.iter_mut().flatten() {
vis.visit_id(id);
vis.visit_path(path)
}
} }
FnKind::Closure(binder, coroutine_kind, decl, body) => { FnKind::Closure(binder, coroutine_kind, decl, body) => {
vis.visit_closure_binder(binder); vis.visit_closure_binder(binder);

View file

@ -892,7 +892,14 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
_ctxt, _ctxt,
_ident, _ident,
_vis, _vis,
Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, contract, body }, Fn {
defaultness: _,
sig: FnSig { header, decl, span: _ },
generics,
contract,
body,
define_opaque,
},
) => { ) => {
// Identifier and visibility are visited as a part of the item. // Identifier and visibility are visited as a part of the item.
try_visit!(visitor.visit_fn_header(header)); try_visit!(visitor.visit_fn_header(header));
@ -900,6 +907,9 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
try_visit!(visitor.visit_fn_decl(decl)); try_visit!(visitor.visit_fn_decl(decl));
visit_opt!(visitor, visit_contract, contract); visit_opt!(visitor, visit_contract, contract);
visit_opt!(visitor, visit_block, body); visit_opt!(visitor, visit_block, body);
for (id, path) in define_opaque.iter().flatten() {
try_visit!(visitor.visit_path(path, *id))
}
} }
FnKind::Closure(binder, coroutine_kind, decl, body) => { FnKind::Closure(binder, coroutine_kind, decl, body) => {
try_visit!(visitor.visit_closure_binder(binder)); try_visit!(visitor.visit_closure_binder(binder));
@ -1203,7 +1213,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
FnKind::Closure(binder, coroutine_kind, fn_decl, body), FnKind::Closure(binder, coroutine_kind, fn_decl, body),
*span, *span,
*id *id
)) ));
} }
ExprKind::Block(block, opt_label) => { ExprKind::Block(block, opt_label) => {
visit_opt!(visitor, visit_label, opt_label); visit_opt!(visitor, visit_label, opt_label);

View file

@ -3,10 +3,9 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt; use rustc_ast::visit::AssocCtxt;
use rustc_ast::*; use rustc_ast::*;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::PredicateOrigin;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, PredicateOrigin};
use rustc_index::{IndexSlice, IndexVec}; use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@ -209,6 +208,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics, generics,
body, body,
contract, contract,
define_opaque,
.. ..
}) => { }) => {
self.with_new_scopes(*fn_sig_span, |this| { self.with_new_scopes(*fn_sig_span, |this| {
@ -237,6 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
header: this.lower_fn_header(*header, hir::Safety::Safe, attrs), header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
span: this.lower_span(*fn_sig_span), span: this.lower_span(*fn_sig_span),
}; };
this.lower_define_opaque(hir_id, &define_opaque);
hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() } hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
}) })
} }
@ -779,7 +780,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
(generics, kind, expr.is_some()) (generics, kind, expr.is_some())
} }
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
// FIXME(contracts): Deny contract here since it won't apply to // FIXME(contracts): Deny contract here since it won't apply to
// any impl method or callees. // any impl method or callees.
let names = self.lower_fn_params_to_names(&sig.decl); let names = self.lower_fn_params_to_names(&sig.decl);
@ -791,9 +792,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind, sig.header.coroutine_kind,
attrs, attrs,
); );
if define_opaque.is_some() {
self.dcx().span_err(
i.span,
"only trait methods with default bodies can define opaque types",
);
}
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
} }
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), contract, .. }) => { AssocItemKind::Fn(box Fn {
sig,
generics,
body: Some(body),
contract,
define_opaque,
..
}) => {
let body_id = self.lower_maybe_coroutine_body( let body_id = self.lower_maybe_coroutine_body(
sig.span, sig.span,
i.span, i.span,
@ -812,6 +826,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind, sig.header.coroutine_kind,
attrs, attrs,
); );
self.lower_define_opaque(hir_id, &define_opaque);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
} }
AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => { AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
@ -911,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ImplItemKind::Const(ty, body) hir::ImplItemKind::Const(ty, body)
}, },
), ),
AssocItemKind::Fn(box Fn { sig, generics, body, contract, .. }) => { AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
let body_id = self.lower_maybe_coroutine_body( let body_id = self.lower_maybe_coroutine_body(
sig.span, sig.span,
i.span, i.span,
@ -930,6 +945,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind, sig.header.coroutine_kind,
attrs, attrs,
); );
self.lower_define_opaque(hir_id, &define_opaque);
(generics, hir::ImplItemKind::Fn(sig, body_id)) (generics, hir::ImplItemKind::Fn(sig, body_id))
} }
@ -1657,6 +1673,35 @@ impl<'hir> LoweringContext<'_, 'hir> {
(lowered_generics, res) (lowered_generics, res)
} }
pub(super) fn lower_define_opaque(
&mut self,
hir_id: HirId,
define_opaque: &Option<ThinVec<(NodeId, Path)>>,
) {
assert_eq!(self.define_opaque, None);
assert!(hir_id.is_owner());
let Some(define_opaque) = define_opaque.as_ref() else {
return;
};
let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
let res = self.resolver.get_partial_res(*id).unwrap();
let Some(did) = res.expect_full_res().opt_def_id() else {
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
return None;
};
let Some(did) = did.as_local() else {
self.dcx().span_err(
path.span,
"only opaque types defined in the local crate can be defined",
);
return None;
};
Some((self.lower_span(path.span), did))
});
let define_opaque = self.arena.alloc_from_iter(define_opaque);
self.define_opaque = Some(define_opaque);
}
pub(super) fn lower_generic_bound_predicate( pub(super) fn lower_generic_bound_predicate(
&mut self, &mut self,
ident: Ident, ident: Ident,

View file

@ -35,6 +35,7 @@
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(exact_size_is_empty)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(rustdoc_internals)] #![feature(rustdoc_internals)]
@ -98,6 +99,8 @@ struct LoweringContext<'a, 'hir> {
/// Bodies inside the owner being lowered. /// Bodies inside the owner being lowered.
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
/// `#[define_opaque]` attributes
define_opaque: Option<&'hir [(Span, LocalDefId)]>,
/// Attributes inside the owner being lowered. /// Attributes inside the owner being lowered.
attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>, attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
/// Collect items that were created by lowering the current owner. /// Collect items that were created by lowering the current owner.
@ -155,6 +158,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// HirId handling. // HirId handling.
bodies: Vec::new(), bodies: Vec::new(),
define_opaque: None,
attrs: SortedMap::default(), attrs: SortedMap::default(),
children: Vec::default(), children: Vec::default(),
contract_ensures: None, contract_ensures: None,
@ -547,6 +551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let current_attrs = std::mem::take(&mut self.attrs); let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies); let current_bodies = std::mem::take(&mut self.bodies);
let current_define_opaque = std::mem::take(&mut self.define_opaque);
let current_ident_and_label_to_local_id = let current_ident_and_label_to_local_id =
std::mem::take(&mut self.ident_and_label_to_local_id); std::mem::take(&mut self.ident_and_label_to_local_id);
@ -580,6 +585,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.attrs = current_attrs; self.attrs = current_attrs;
self.bodies = current_bodies; self.bodies = current_bodies;
self.define_opaque = current_define_opaque;
self.ident_and_label_to_local_id = current_ident_and_label_to_local_id; self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -599,6 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
let attrs = std::mem::take(&mut self.attrs); let attrs = std::mem::take(&mut self.attrs);
let mut bodies = std::mem::take(&mut self.bodies); let mut bodies = std::mem::take(&mut self.bodies);
let define_opaque = std::mem::take(&mut self.define_opaque);
let trait_map = std::mem::take(&mut self.trait_map); let trait_map = std::mem::take(&mut self.trait_map);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -618,7 +625,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let num_nodes = self.item_local_id_counter.as_usize(); let num_nodes = self.item_local_id_counter.as_usize();
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
} }

View file

@ -917,7 +917,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(self, visit_attribute, &item.attrs); walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again. return; // Avoid visiting again.
} }
ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, contract: _, body }) => { ItemKind::Fn(
func
@ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ },
) => {
self.check_defaultness(item.span, *defaultness); self.check_defaultness(item.span, *defaultness);
let is_intrinsic = let is_intrinsic =

View file

@ -24,7 +24,6 @@ use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::IdentPrinter; use rustc_span::symbol::IdentPrinter;
use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym}; use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym};
use thin_vec::ThinVec;
use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::Breaks::{Consistent, Inconsistent};
use crate::pp::{self, Breaks}; use crate::pp::{self, Breaks};
@ -1978,15 +1977,7 @@ impl<'a> State<'a> {
) { ) {
self.ibox(INDENT_UNIT); self.ibox(INDENT_UNIT);
self.print_formal_generic_params(generic_params); self.print_formal_generic_params(generic_params);
let generics = ast::Generics { let generics = ast::Generics::default();
params: ThinVec::new(),
where_clause: ast::WhereClause {
has_where_token: false,
predicates: ThinVec::new(),
span: DUMMY_SP,
},
span: DUMMY_SP,
};
let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() }; let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
self.print_fn(decl, header, name, &generics); self.print_fn(decl, header, name, &generics);
self.end(); self.end();

View file

@ -650,7 +650,16 @@ impl<'a> State<'a> {
attrs: &[ast::Attribute], attrs: &[ast::Attribute],
func: &ast::Fn, func: &ast::Fn,
) { ) {
let ast::Fn { defaultness, generics, sig, contract, body } = func; let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
if let Some(define_opaque) = define_opaque {
for (_, path) in define_opaque {
self.word("define opaques from ");
self.print_path(path, false, 0);
self.word(",");
}
}
if body.is_some() { if body.is_some() {
self.head(""); self.head("");
} }
@ -698,7 +707,7 @@ impl<'a> State<'a> {
} }
self.print_generic_params(&generics.params); self.print_generic_params(&generics.params);
self.print_fn_params_and_ret(decl, false); self.print_fn_params_and_ret(decl, false);
self.print_where_clause(&generics.where_clause) self.print_where_clause(&generics.where_clause);
} }
pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) { pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {

View file

@ -180,6 +180,7 @@ pub(super) fn take_opaques_and_register_member_constraints<'tcx>(
/// // Equivalent to: /// // Equivalent to:
/// # mod dummy { use super::*; /// # mod dummy { use super::*;
/// type FooReturn<'a, T> = impl Foo<'a>; /// type FooReturn<'a, T> = impl Foo<'a>;
/// #[define_opaque(FooReturn)]
/// fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> { /// fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> {
/// (x, y) /// (x, y)
/// } /// }

View file

@ -88,6 +88,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
generics: Generics::default(), generics: Generics::default(),
contract: None, contract: None,
body, body,
define_opaque: None,
})); }));
let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)]; let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];

View file

@ -247,6 +247,7 @@ mod llvm_enzyme {
generics: Generics::default(), generics: Generics::default(),
contract: None, contract: None,
body: Some(d_body), body: Some(d_body),
define_opaque: None,
}); });
let mut rustc_ad_attr = let mut rustc_ad_attr =
P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff))); P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));

View file

@ -0,0 +1,54 @@
use rustc_ast::{DUMMY_NODE_ID, ast};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::Span;
pub(crate) fn expand(
ecx: &mut ExtCtxt<'_>,
_expand_span: Span,
meta_item: &ast::MetaItem,
mut item: Annotatable,
) -> Vec<Annotatable> {
let define_opaque = match &mut item {
Annotatable::Item(p) => match &mut p.kind {
ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
_ => None,
},
Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind {
ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaque),
_ => None,
},
Annotatable::Stmt(s) => match &mut s.kind {
ast::StmtKind::Item(p) => match &mut p.kind {
ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
_ => None,
},
_ => None,
},
_ => None,
};
let Some(list) = meta_item.meta_item_list() else {
ecx.dcx().span_err(meta_item.span, "expected list of type aliases");
return vec![item];
};
if let Some(define_opaque) = define_opaque {
*define_opaque = Some(
list.iter()
.filter_map(|entry| match entry {
ast::MetaItemInner::MetaItem(meta_item) if meta_item.is_word() => {
Some((DUMMY_NODE_ID, meta_item.path.clone()))
}
_ => {
ecx.dcx().span_err(entry.span(), "expected path to type alias");
None
}
})
.collect(),
);
} else {
ecx.dcx().span_err(meta_item.span, "only functions and methods can define opaque types");
}
vec![item]
}

View file

@ -1040,6 +1040,7 @@ impl<'a> MethodDef<'a> {
generics: fn_generics, generics: fn_generics,
contract: None, contract: None,
body: Some(body_block), body: Some(body_block),
define_opaque: None,
})), })),
tokens: None, tokens: None,
}) })

View file

@ -83,6 +83,7 @@ impl AllocFnFactory<'_, '_> {
generics: Generics::default(), generics: Generics::default(),
contract: None, contract: None,
body, body,
define_opaque: None,
})); }));
let item = self.cx.item( let item = self.cx.item(
self.span, self.span,

View file

@ -39,6 +39,7 @@ mod compile_error;
mod concat; mod concat;
mod concat_bytes; mod concat_bytes;
mod concat_idents; mod concat_idents;
mod define_opaque;
mod derive; mod derive;
mod deriving; mod deriving;
mod edition_panic; mod edition_panic;
@ -114,6 +115,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
bench: test::expand_bench, bench: test::expand_bench,
cfg_accessible: cfg_accessible::Expander, cfg_accessible: cfg_accessible::Expander,
cfg_eval: cfg_eval::expand, cfg_eval: cfg_eval::expand,
define_opaque: define_opaque::expand,
derive: derive::Expander { is_const: false }, derive: derive::Expander { is_const: false },
derive_const: derive::Expander { is_const: true }, derive_const: derive::Expander { is_const: true },
global_allocator: global_allocator::expand, global_allocator: global_allocator::expand,

View file

@ -346,6 +346,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
generics: ast::Generics::default(), generics: ast::Generics::default(),
contract: None, contract: None,
body: Some(main_body), body: Some(main_body),
define_opaque: None,
})); }));
// Honor the reexport_test_harness_main attribute // Honor the reexport_test_harness_main attribute

View file

@ -2,23 +2,21 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
mod helper { pub trait T {
pub trait T { type Item;
type Item; }
}
pub type Alias<'a> = impl T<Item = &'a ()>;
pub type Alias<'a> = impl T<Item = &'a ()>;
struct S;
struct S; impl<'a> T for &'a S {
impl<'a> T for &'a S { type Item = &'a ();
type Item = &'a (); }
}
#[define_opaque(Alias)]
pub fn filter_positive<'a>() -> Alias<'a> { pub fn filter_positive<'a>() -> Alias<'a> {
&S &S
}
} }
use helper::*;
fn with_positive(fun: impl Fn(Alias<'_>)) { fn with_positive(fun: impl Fn(Alias<'_>)) {
fun(filter_positive()); fun(filter_positive());

View file

@ -315,6 +315,7 @@ mod helper {
use super::*; use super::*;
pub type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>; pub type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
impl<O: ForestObligation> ObligationForest<O> { impl<O: ForestObligation> ObligationForest<O> {
#[cfg_attr(not(bootstrap), define_opaque(ObligationTreeIdGenerator))]
pub fn new() -> ObligationForest<O> { pub fn new() -> ObligationForest<O> {
ObligationForest { ObligationForest {
nodes: vec![], nodes: vec![],

View file

@ -7,6 +7,7 @@ This means
type Foo<T> = impl std::fmt::Debug; type Foo<T> = impl std::fmt::Debug;
#[define_opaque(Foo)]
fn foo() -> Foo<u32> { fn foo() -> Foo<u32> {
5u32 5u32
} }
@ -19,6 +20,7 @@ is not accepted. If it were accepted, one could create unsound situations like
type Foo<T> = impl Default; type Foo<T> = impl Default;
#[define_opaque(Foo)]
fn foo() -> Foo<u32> { fn foo() -> Foo<u32> {
5u32 5u32
} }
@ -36,6 +38,7 @@ Instead you need to make the function generic:
type Foo<T> = impl std::fmt::Debug; type Foo<T> = impl std::fmt::Debug;
#[define_opaque(Foo)]
fn foo<U>() -> Foo<U> { fn foo<U>() -> Foo<U> {
5u32 5u32
} }
@ -56,6 +59,7 @@ use std::fmt::Debug;
type Foo<T: Debug> = impl Debug; type Foo<T: Debug> = impl Debug;
#[define_opaque(Foo)]
fn foo<U: Debug>() -> Foo<U> { fn foo<U: Debug>() -> Foo<U> {
Vec::<U>::new() Vec::<U>::new()
} }

View file

@ -209,6 +209,7 @@ pub type LazyFallbackBundle = Arc<LazyLock<FluentBundle, impl FnOnce() -> Fluent
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages. /// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
#[instrument(level = "trace", skip(resources))] #[instrument(level = "trace", skip(resources))]
#[cfg_attr(not(bootstrap), define_opaque(LazyFallbackBundle))]
pub fn fallback_fluent_bundle( pub fn fallback_fluent_bundle(
resources: Vec<&'static str>, resources: Vec<&'static str>,
with_directionality_markers: bool, with_directionality_markers: bool,

View file

@ -780,8 +780,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
} }
} }
Err(err) => { Err(err) => {
let guar = err.emit(); let _guar = err.emit();
fragment_kind.dummy(span, guar) fragment_kind.expect_from_annotatables(iter::once(item))
} }
} }
} }

View file

@ -1307,13 +1307,18 @@ impl Attribute {
#[derive(Debug)] #[derive(Debug)]
pub struct AttributeMap<'tcx> { pub struct AttributeMap<'tcx> {
pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>, pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
/// Preprocessed `#[define_opaque]` attribute.
pub define_opaque: Option<&'tcx [(Span, LocalDefId)]>,
// Only present when the crate hash is needed. // Only present when the crate hash is needed.
pub opt_hash: Option<Fingerprint>, pub opt_hash: Option<Fingerprint>,
} }
impl<'tcx> AttributeMap<'tcx> { impl<'tcx> AttributeMap<'tcx> {
pub const EMPTY: &'static AttributeMap<'static> = pub const EMPTY: &'static AttributeMap<'static> = &AttributeMap {
&AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) }; map: SortedMap::new(),
opt_hash: Some(Fingerprint::ZERO),
define_opaque: None,
};
#[inline] #[inline]
pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {

View file

@ -106,7 +106,7 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
// We ignore the `map` since it refers to information included in `opt_hash` which is // We ignore the `map` since it refers to information included in `opt_hash` which is
// hashed in the collector and used for the crate hash. // hashed in the collector and used for the crate hash.
let AttributeMap { opt_hash, map: _ } = *self; let AttributeMap { opt_hash, define_opaque: _, map: _ } = *self;
opt_hash.unwrap().hash_stable(hcx, hasher); opt_hash.unwrap().hash_stable(hcx, hasher);
} }
} }

View file

@ -504,12 +504,9 @@ hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by
hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`
.note = this item must mention the opaque type in its signature in order to be able to register hidden types .note = consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
.opaque = this opaque type is supposed to be constrained
hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, but has it in its signature
.note = consider moving the opaque type's declaration and defining uses into a separate module
.opaque = this opaque type is in the signature
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]` hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`

View file

@ -392,6 +392,12 @@ fn best_definition_site_of_opaque<'tcx>(
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
// Don't try to check items that cannot possibly constrain the type.
if !opaque_types_defined_by.contains(&self.opaque_def_id) {
return ControlFlow::Continue(());
}
if let Some(hidden_ty) = if let Some(hidden_ty) =
self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
{ {
@ -451,19 +457,7 @@ fn best_definition_site_of_opaque<'tcx>(
None None
} }
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
let scope = tcx.hir_get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id)); tcx.hir_walk_toplevel_module(&mut locator).break_value()
let found = if scope == hir::CRATE_HIR_ID {
tcx.hir_walk_toplevel_module(&mut locator)
} else {
match tcx.hir_node(scope) {
Node::Item(it) => locator.visit_item(it),
Node::ImplItem(it) => locator.visit_impl_item(it),
Node::TraitItem(it) => locator.visit_trait_item(it),
Node::ForeignItem(it) => locator.visit_foreign_item(it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
};
found.break_value()
} }
} }
} }

View file

@ -1,14 +1,13 @@
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
use crate::errors::{TaitForwardCompat, TaitForwardCompat2, UnconstrainedOpaqueType}; use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
/// Checks "defining uses" of opaque `impl Trait` in associated types. /// Checks "defining uses" of opaque `impl Trait` in associated types.
/// These can only be defined by associated items of the same trait. /// These can only be defined by associated items of the same trait.
@ -82,38 +81,9 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
/// ``` /// ```
#[instrument(skip(tcx), level = "debug")] #[instrument(skip(tcx), level = "debug")]
pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let scope = tcx.hir_get_defining_scope(hir_id);
let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
debug!(?scope); tcx.hir_walk_toplevel_module(&mut locator);
if scope == hir::CRATE_HIR_ID {
tcx.hir_walk_toplevel_module(&mut locator);
} else {
trace!("scope={:#?}", tcx.hir_node(scope));
match tcx.hir_node(scope) {
// We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
// This allows our visitor to process the defining item itself, causing
// it to pick up any 'sibling' defining uses.
//
// For example, this code:
// ```
// fn foo() {
// type Blah = impl Debug;
// let my_closure = || -> Blah { true };
// }
// ```
//
// requires us to explicitly process `foo()` in order
// to notice the defining usage of `Blah`.
Node::Item(it) => locator.visit_item(it),
Node::ImplItem(it) => locator.visit_impl_item(it),
Node::TraitItem(it) => locator.visit_trait_item(it),
Node::ForeignItem(it) => locator.visit_foreign_item(it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
}
if let Some(hidden) = locator.found { if let Some(hidden) = locator.found {
// Only check against typeck if we didn't already error // Only check against typeck if we didn't already error
@ -137,12 +107,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id), span: tcx.def_span(def_id),
name: tcx.item_ident(parent_def_id.to_def_id()), name: tcx.item_ident(parent_def_id.to_def_id()),
what: match tcx.hir_node(scope) { what: "crate",
_ if scope == hir::CRATE_HIR_ID => "module",
Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
_ => "item",
},
}); });
Ty::new_error(tcx, reported) Ty::new_error(tcx, reported)
} }
@ -176,6 +141,13 @@ impl TaitConstraintLocator<'_> {
return; return;
} }
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
// Don't try to check items that cannot possibly constrain the type.
if !opaque_types_defined_by.contains(&self.def_id) {
debug!("no constraint: no opaque types defined");
return;
}
// Function items with `_` in their return type already emit an error, skip any // Function items with `_` in their return type already emit an error, skip any
// "non-defining use" errors for them. // "non-defining use" errors for them.
// Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former
@ -215,8 +187,6 @@ impl TaitConstraintLocator<'_> {
return; return;
} }
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
let mut constrained = false; let mut constrained = false;
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types { for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
if opaque_type_key.def_id != self.def_id { if opaque_type_key.def_id != self.def_id {
@ -224,20 +194,6 @@ impl TaitConstraintLocator<'_> {
} }
constrained = true; constrained = true;
if !opaque_types_defined_by.contains(&self.def_id) {
let guar = self.tcx.dcx().emit_err(TaitForwardCompat {
span: hidden_type.span,
item_span: self
.tcx
.def_ident_span(item_def_id)
.unwrap_or_else(|| self.tcx.def_span(item_def_id)),
});
// Avoid "opaque type not constrained" errors on the opaque itself.
self.found = Some(ty::OpaqueHiddenType {
span: DUMMY_SP,
ty: Ty::new_error(self.tcx, guar),
});
}
let concrete_type = let concrete_type =
self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params( self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
opaque_type_key, opaque_type_key,
@ -309,19 +265,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
} }
fn visit_item(&mut self, it: &'tcx Item<'tcx>) { fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
trace!(?it.owner_id); trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope. self.check(it.owner_id.def_id);
if it.owner_id.def_id != self.def_id { intravisit::walk_item(self, it);
self.check(it.owner_id.def_id);
intravisit::walk_item(self, it);
}
} }
fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
trace!(?it.owner_id); trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope. self.check(it.owner_id.def_id);
if it.owner_id.def_id != self.def_id { intravisit::walk_impl_item(self, it);
self.check(it.owner_id.def_id);
intravisit::walk_impl_item(self, it);
}
} }
fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
trace!(?it.owner_id); trace!(?it.owner_id);

View file

@ -424,16 +424,6 @@ pub(crate) struct UnconstrainedOpaqueType {
pub what: &'static str, pub what: &'static str,
} }
#[derive(Diagnostic)]
#[diag(hir_analysis_tait_forward_compat)]
#[note]
pub(crate) struct TaitForwardCompat {
#[primary_span]
pub span: Span,
#[note]
pub item_span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_tait_forward_compat2)] #[diag(hir_analysis_tait_forward_compat2)]
#[note] #[note]

View file

@ -43,6 +43,7 @@ declare_lint! {
/// ///
/// type Tait = impl Sized; /// type Tait = impl Sized;
/// ///
/// #[define_opaque(Tait)]
/// fn test() -> impl Trait<Assoc = Tait> { /// fn test() -> impl Trait<Assoc = Tait> {
/// 42 /// 42
/// } /// }

View file

@ -454,6 +454,7 @@ mod helper {
/// Like [`SwitchTargets::target_for_value`], but returning the same type as /// Like [`SwitchTargets::target_for_value`], but returning the same type as
/// [`Terminator::successors`]. /// [`Terminator::successors`].
#[inline] #[inline]
#[cfg_attr(not(bootstrap), define_opaque(Successors))]
pub fn successors_for_value(&self, value: u128) -> Successors<'_> { pub fn successors_for_value(&self, value: u128) -> Successors<'_> {
let target = self.target_for_value(value); let target = self.target_for_value(value);
(&[]).into_iter().copied().chain(Some(target)) (&[]).into_iter().copied().chain(Some(target))
@ -462,6 +463,7 @@ mod helper {
impl<'tcx> TerminatorKind<'tcx> { impl<'tcx> TerminatorKind<'tcx> {
#[inline] #[inline]
#[cfg_attr(not(bootstrap), define_opaque(Successors))]
pub fn successors(&self) -> Successors<'_> { pub fn successors(&self) -> Successors<'_> {
use self::TerminatorKind::*; use self::TerminatorKind::*;
match *self { match *self {
@ -500,6 +502,7 @@ mod helper {
} }
#[inline] #[inline]
#[cfg_attr(not(bootstrap), define_opaque(SuccessorsMut))]
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
use self::TerminatorKind::*; use self::TerminatorKind::*;
match *self { match *self {

View file

@ -24,6 +24,7 @@ pub trait EraseType: Copy {
pub type Erase<T: EraseType> = Erased<impl Copy>; pub type Erase<T: EraseType> = Erased<impl Copy>;
#[inline(always)] #[inline(always)]
#[cfg_attr(not(bootstrap), define_opaque(Erase))]
pub fn erase<T: EraseType>(src: T) -> Erase<T> { pub fn erase<T: EraseType>(src: T) -> Erase<T> {
// Ensure the sizes match // Ensure the sizes match
const { const {
@ -47,6 +48,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
/// Restores an erased value. /// Restores an erased value.
#[inline(always)] #[inline(always)]
#[cfg_attr(not(bootstrap), define_opaque(Erase))]
pub fn restore<T: EraseType>(value: Erase<T>) -> T { pub fn restore<T: EraseType>(value: Erase<T>) -> T {
let value: Erased<<T as EraseType>::Result> = value; let value: Erased<<T as EraseType>::Result> = value;
// See comment in `erase` for why we use `transmute_unchecked`. // See comment in `erase` for why we use `transmute_unchecked`.

View file

@ -217,7 +217,14 @@ impl<'a> Parser<'a> {
self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?; self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
( (
ident, ident,
ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, contract, body })), ItemKind::Fn(Box::new(Fn {
defaultness: def_(),
sig,
generics,
contract,
body,
define_opaque: None,
})),
) )
} else if self.eat_keyword(exp!(Extern)) { } else if self.eat_keyword(exp!(Extern)) {
if self.eat_keyword(exp!(Crate)) { if self.eat_keyword(exp!(Crate)) {

View file

@ -397,32 +397,37 @@ pub(crate) enum AliasPossibility {
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub(crate) enum PathSource<'a> { pub(crate) enum PathSource<'a> {
// Type paths `Path`. /// Type paths `Path`.
Type, Type,
// Trait paths in bounds or impls. /// Trait paths in bounds or impls.
Trait(AliasPossibility), Trait(AliasPossibility),
// Expression paths `path`, with optional parent context. /// Expression paths `path`, with optional parent context.
Expr(Option<&'a Expr>), Expr(Option<&'a Expr>),
// Paths in path patterns `Path`. /// Paths in path patterns `Path`.
Pat, Pat,
// Paths in struct expressions and patterns `Path { .. }`. /// Paths in struct expressions and patterns `Path { .. }`.
Struct, Struct,
// Paths in tuple struct patterns `Path(..)`. /// Paths in tuple struct patterns `Path(..)`.
TupleStruct(Span, &'a [Span]), TupleStruct(Span, &'a [Span]),
// `m::A::B` in `<T as m::A>::B::C`. /// `m::A::B` in `<T as m::A>::B::C`.
TraitItem(Namespace), TraitItem(Namespace),
// Paths in delegation item /// Paths in delegation item
Delegation, Delegation,
/// An arg in a `use<'a, N>` precise-capturing bound. /// An arg in a `use<'a, N>` precise-capturing bound.
PreciseCapturingArg(Namespace), PreciseCapturingArg(Namespace),
// Paths that end with `(..)`, for return type notation. /// Paths that end with `(..)`, for return type notation.
ReturnTypeNotation, ReturnTypeNotation,
/// Paths from `#[define_opaque]` attributes
DefineOpaques,
} }
impl<'a> PathSource<'a> { impl<'a> PathSource<'a> {
fn namespace(self) -> Namespace { fn namespace(self) -> Namespace {
match self { match self {
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS, PathSource::Type
| PathSource::Trait(_)
| PathSource::Struct
| PathSource::DefineOpaques => TypeNS,
PathSource::Expr(..) PathSource::Expr(..)
| PathSource::Pat | PathSource::Pat
| PathSource::TupleStruct(..) | PathSource::TupleStruct(..)
@ -443,6 +448,7 @@ impl<'a> PathSource<'a> {
| PathSource::ReturnTypeNotation => true, | PathSource::ReturnTypeNotation => true,
PathSource::Trait(_) PathSource::Trait(_)
| PathSource::TraitItem(..) | PathSource::TraitItem(..)
| PathSource::DefineOpaques
| PathSource::Delegation | PathSource::Delegation
| PathSource::PreciseCapturingArg(..) => false, | PathSource::PreciseCapturingArg(..) => false,
} }
@ -450,6 +456,7 @@ impl<'a> PathSource<'a> {
fn descr_expected(self) -> &'static str { fn descr_expected(self) -> &'static str {
match &self { match &self {
PathSource::DefineOpaques => "type alias or associated type with opaqaue types",
PathSource::Type => "type", PathSource::Type => "type",
PathSource::Trait(_) => "trait", PathSource::Trait(_) => "trait",
PathSource::Pat => "unit struct, unit variant or constant", PathSource::Pat => "unit struct, unit variant or constant",
@ -493,6 +500,19 @@ impl<'a> PathSource<'a> {
pub(crate) fn is_expected(self, res: Res) -> bool { pub(crate) fn is_expected(self, res: Res) -> bool {
match self { match self {
PathSource::DefineOpaques => {
matches!(
res,
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::AssocTy,
_
) | Res::SelfTyAlias { .. }
)
}
PathSource::Type => matches!( PathSource::Type => matches!(
res, res,
Res::Def( Res::Def(
@ -572,16 +592,16 @@ impl<'a> PathSource<'a> {
match (self, has_unexpected_resolution) { match (self, has_unexpected_resolution) {
(PathSource::Trait(_), true) => E0404, (PathSource::Trait(_), true) => E0404,
(PathSource::Trait(_), false) => E0405, (PathSource::Trait(_), false) => E0405,
(PathSource::Type, true) => E0573, (PathSource::Type | PathSource::DefineOpaques, true) => E0573,
(PathSource::Type, false) => E0412, (PathSource::Type | PathSource::DefineOpaques, false) => E0412,
(PathSource::Struct, true) => E0574, (PathSource::Struct, true) => E0574,
(PathSource::Struct, false) => E0422, (PathSource::Struct, false) => E0422,
(PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423, (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
(PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425, (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
(PathSource::Pat | PathSource::TupleStruct(..), true) => E0532, (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
(PathSource::Pat | PathSource::TupleStruct(..), false) => E0531, (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
(PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575, (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, true) => E0575,
(PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576, (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, false) => E0576,
(PathSource::PreciseCapturingArg(..), true) => E0799, (PathSource::PreciseCapturingArg(..), true) => E0799,
(PathSource::PreciseCapturingArg(..), false) => E0800, (PathSource::PreciseCapturingArg(..), false) => E0800,
} }
@ -2006,6 +2026,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
| PathSource::Pat | PathSource::Pat
| PathSource::Struct | PathSource::Struct
| PathSource::TupleStruct(..) | PathSource::TupleStruct(..)
| PathSource::DefineOpaques
| PathSource::Delegation => true, | PathSource::Delegation => true,
}; };
if inferred { if inferred {
@ -2619,7 +2640,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
); );
} }
ItemKind::Fn(box Fn { ref generics, .. }) => { ItemKind::Fn(box Fn { ref generics, ref define_opaque, .. }) => {
self.with_generic_param_rib( self.with_generic_param_rib(
&generics.params, &generics.params,
RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
@ -2630,6 +2651,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}, },
|this| visit::walk_item(this, item), |this| visit::walk_item(this, item),
); );
for (id, path) in define_opaque.iter().flatten() {
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
}
} }
ItemKind::Enum(_, ref generics) ItemKind::Enum(_, ref generics)
@ -3100,8 +3125,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}, },
); );
} }
AssocItemKind::Fn(box Fn { generics, .. }) => { AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
for (id, path) in define_opaque.iter().flatten() {
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
}
} }
AssocItemKind::Delegation(delegation) => { AssocItemKind::Delegation(delegation) => {
self.with_generic_param_rib( self.with_generic_param_rib(
@ -3311,7 +3340,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
}, },
); );
} }
AssocItemKind::Fn(box Fn { generics, .. }) => { AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
debug!("resolve_implementation AssocItemKind::Fn"); debug!("resolve_implementation AssocItemKind::Fn");
// We also need a new scope for the impl item type parameters. // We also need a new scope for the impl item type parameters.
self.with_generic_param_rib( self.with_generic_param_rib(
@ -3338,6 +3367,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
visit::walk_assoc_item(this, item, AssocCtxt::Impl) visit::walk_assoc_item(this, item, AssocCtxt::Impl)
}, },
); );
for (id, path) in define_opaque.iter().flatten() {
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
}
} }
AssocItemKind::Type(box TyAlias { generics, .. }) => { AssocItemKind::Type(box TyAlias { generics, .. }) => {
self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty()); self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());

View file

@ -779,6 +779,7 @@ symbols! {
default_method_body_is_const, default_method_body_is_const,
default_type_parameter_fallback, default_type_parameter_fallback,
default_type_params, default_type_params,
define_opaque,
delayed_bug_from_inside_query, delayed_bug_from_inside_query,
deny, deny,
deprecated, deprecated,

View file

@ -395,11 +395,28 @@ impl<T> Trait<T> for X {
let sp = tcx let sp = tcx
.def_ident_span(body_owner_def_id) .def_ident_span(body_owner_def_id)
.unwrap_or_else(|| tcx.def_span(body_owner_def_id)); .unwrap_or_else(|| tcx.def_span(body_owner_def_id));
diag.span_note( let mut alias_def_id = opaque_ty.def_id;
sp, while let DefKind::OpaqueTy = tcx.def_kind(alias_def_id) {
"this item must have the opaque type in its signature in order to \ alias_def_id = tcx.parent(alias_def_id);
be able to register hidden types", }
); let opaque_path = tcx.def_path_str(alias_def_id);
// FIXME(type_alias_impl_trait): make this a structured suggestion
match tcx.opaque_ty_origin(opaque_ty.def_id) {
rustc_hir::OpaqueTyOrigin::FnReturn { .. } => {}
rustc_hir::OpaqueTyOrigin::AsyncFn { .. } => {}
rustc_hir::OpaqueTyOrigin::TyAlias {
in_assoc_ty: false, ..
} => {
diag.span_note(
sp,
format!("this item must have a `#[define_opaque({opaque_path})]` \
attribute to be able to define hidden types"),
);
}
rustc_hir::OpaqueTyOrigin::TyAlias {
in_assoc_ty: true, ..
} => {}
}
} }
// If two if arms can be coerced to a trait object, provide a structured // If two if arms can be coerced to a trait object, provide a structured
// suggestion. // suggestion.

View file

@ -7,6 +7,7 @@ edition = "2024"
# tidy-alphabetical-start # tidy-alphabetical-start
itertools = "0.12" itertools = "0.12"
rustc_abi = { path = "../rustc_abi" } rustc_abi = { path = "../rustc_abi" }
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" } rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fluent_macro = { path = "../rustc_fluent_macro" }

View file

@ -1,8 +1,8 @@
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_hir::{CRATE_HIR_ID, intravisit};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
@ -30,14 +30,21 @@ enum CollectionMode {
/// For impl trait in assoc types we only permit collecting them from /// For impl trait in assoc types we only permit collecting them from
/// associated types of the same impl block. /// associated types of the same impl block.
ImplTraitInAssocTypes, ImplTraitInAssocTypes,
TypeAliasImplTraitTransition, /// When collecting for an explicit `#[define_opaque]` attribute, find all TAITs
Taits,
/// The default case, only collect RPITs and AsyncFn return types, as these are
/// always defined by the current item.
RpitAndAsyncFnOnly,
} }
impl<'tcx> OpaqueTypeCollector<'tcx> { impl<'tcx> OpaqueTypeCollector<'tcx> {
fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self { fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
let mode = match tcx.def_kind(tcx.local_parent(item)) { let mode = match tcx.def_kind(item) {
DefKind::Impl { of_trait: true } => CollectionMode::ImplTraitInAssocTypes, DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => {
_ => CollectionMode::TypeAliasImplTraitTransition, CollectionMode::ImplTraitInAssocTypes
}
DefKind::TyAlias => CollectionMode::Taits,
_ => CollectionMode::RpitAndAsyncFnOnly,
}; };
Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode } Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode }
} }
@ -73,40 +80,6 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
} }
} }
/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`.
///
/// Example:
/// ```ignore UNSOLVED (is this a bug?)
/// # #![feature(type_alias_impl_trait)]
/// pub mod foo {
/// pub mod bar {
/// pub trait Bar { /* ... */ }
/// pub type Baz = impl Bar;
///
/// # impl Bar for () {}
/// fn f1() -> Baz { /* ... */ }
/// }
/// fn f2() -> bar::Baz { /* ... */ }
/// }
/// ```
///
/// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`.
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
#[instrument(level = "trace", skip(self), ret)]
fn check_tait_defining_scope(&self, opaque_def_id: LocalDefId) -> bool {
let mut hir_id = self.tcx.local_def_id_to_hir_id(self.item);
let opaque_hir_id = self.tcx.local_def_id_to_hir_id(opaque_def_id);
// Named opaque types can be defined by any siblings or children of siblings.
let scope = self.tcx.hir_get_defining_scope(opaque_hir_id);
// We walk up the node tree until we hit the root or the scope of the opaque type.
while hir_id != scope && hir_id != CRATE_HIR_ID {
hir_id = self.tcx.hir_get_parent_item(hir_id).into();
}
// Syntactically, we are allowed to define the concrete type if:
hir_id == scope
}
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
fn collect_taits_declared_in_body(&mut self) { fn collect_taits_declared_in_body(&mut self) {
let body = self.tcx.hir_body_owned_by(self.item).value; let body = self.tcx.hir_body_owned_by(self.item).value;
@ -139,18 +112,31 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
} }
// TAITs outside their defining scopes are ignored. // TAITs outside their defining scopes are ignored.
let origin = self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local()); match self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local()) {
trace!(?origin);
match origin {
rustc_hir::OpaqueTyOrigin::FnReturn { .. } rustc_hir::OpaqueTyOrigin::FnReturn { .. }
| rustc_hir::OpaqueTyOrigin::AsyncFn { .. } => {} | rustc_hir::OpaqueTyOrigin::AsyncFn { .. } => {}
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => { rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => match self.mode {
if !in_assoc_ty && !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) { // If we are collecting opaques in an assoc method, we are only looking at assoc types
return; // mentioned in the assoc method and only at opaques defined in there. We do not
// want to collect TAITs
CollectionMode::ImplTraitInAssocTypes => {
if !in_assoc_ty {
return;
}
} }
} // If we are collecting opaques referenced from a `define_opaque` attribute, we
// do not want to look at opaques defined in associated types. Those can only be
// defined by methods on the same impl.
CollectionMode::Taits => {
if in_assoc_ty {
return;
}
}
CollectionMode::RpitAndAsyncFnOnly => return,
},
} }
trace!(?alias_ty, "adding");
self.opaques.push(alias_ty.def_id.expect_local()); self.opaques.push(alias_ty.def_id.expect_local());
let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count; let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count;
@ -192,6 +178,32 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
} }
} }
} }
/// Checks the `#[define_opaque]` attributes on items and collectes opaques to define
/// from the referenced types.
#[instrument(level = "trace", skip(self))]
fn collect_taits_from_defines_attr(&mut self) {
let hir_id = self.tcx.local_def_id_to_hir_id(self.item);
if !hir_id.is_owner() {
return;
}
let Some(defines) = self.tcx.hir_attrs(hir_id.owner).define_opaque else {
return;
};
for &(span, define) in defines {
trace!(?define);
let mode = std::mem::replace(&mut self.mode, CollectionMode::Taits);
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
// case it was capturing too much.
self.mode = CollectionMode::RpitAndAsyncFnOnly;
}
} }
impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> { impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
@ -210,6 +222,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
self.visit_opaque_ty(alias_ty); self.visit_opaque_ty(alias_ty);
} }
// Skips type aliases, as they are meant to be transparent. // Skips type aliases, as they are meant to be transparent.
// FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly?
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => { ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
self.tcx self.tcx
.type_of(alias_ty.def_id) .type_of(alias_ty.def_id)
@ -283,28 +296,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
self.visit_opaque_ty(alias_ty); self.visit_opaque_ty(alias_ty);
} }
} }
ty::Adt(def, _) if def.did().is_local() => {
if let CollectionMode::ImplTraitInAssocTypes = self.mode {
return;
}
if !self.seen.insert(def.did().expect_local()) {
return;
}
for variant in def.variants().iter() {
for field in variant.fields.iter() {
// Don't use the `ty::Adt` args, we either
// * found the opaque in the args
// * will find the opaque in the uninstantiated fields
// The only other situation that can occur is that after instantiating,
// some projection resolves to an opaque that we would have otherwise
// not found. While we could instantiate and walk those, that would mean we
// would have to walk all generic parameters of an Adt, which can quickly
// degenerate into looking at an exponential number of types.
let ty = self.tcx.type_of(field.did).instantiate_identity();
self.visit_spanned(self.tcx.def_span(field.did), ty);
}
}
}
_ => trace!(kind=?t.kind()), _ => trace!(kind=?t.kind()),
} }
} }
@ -317,7 +308,9 @@ fn opaque_types_defined_by<'tcx>(
let kind = tcx.def_kind(item); let kind = tcx.def_kind(item);
trace!(?kind); trace!(?kind);
let mut collector = OpaqueTypeCollector::new(tcx, item); let mut collector = OpaqueTypeCollector::new(tcx, item);
collector.collect_taits_from_defines_attr();
super::sig_types::walk_types(tcx, item, &mut collector); super::sig_types::walk_types(tcx, item, &mut collector);
match kind { match kind {
DefKind::AssocFn DefKind::AssocFn
| DefKind::Fn | DefKind::Fn
@ -350,8 +343,7 @@ fn opaque_types_defined_by<'tcx>(
| DefKind::GlobalAsm | DefKind::GlobalAsm
| DefKind::Impl { .. } | DefKind::Impl { .. }
| DefKind::SyntheticCoroutineBody => {} | DefKind::SyntheticCoroutineBody => {}
// Closures and coroutines are type checked with their parent, so we need to allow all // Closures and coroutines are type checked with their parent
// opaques from the closure signature *and* from the parent body.
DefKind::Closure | DefKind::InlineConst => { DefKind::Closure | DefKind::InlineConst => {
collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item))); collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
} }

View file

@ -1743,6 +1743,21 @@ pub(crate) mod builtin {
/* compiler built-in */ /* compiler built-in */
} }
/// Provide a list of type aliases and other opaque-type-containing type definitions.
/// This list will be used in the body of the item it is applied to to define opaque
/// types' hidden types.
/// Can only be applied to things that have bodies.
#[unstable(
feature = "type_alias_impl_trait",
issue = "63063",
reason = "`type_alias_impl_trait` has open design concerns"
)]
#[rustc_builtin_macro]
#[cfg(not(bootstrap))]
pub macro define_opaque($($tt:tt)*) {
/* compiler built-in */
}
/// Unstable placeholder for type ascription. /// Unstable placeholder for type ascription.
#[allow_internal_unstable(builtin_syntax)] #[allow_internal_unstable(builtin_syntax)]
#[unstable( #[unstable(

View file

@ -111,3 +111,11 @@ pub use crate::macros::builtin::type_ascribe;
reason = "placeholder syntax for deref patterns" reason = "placeholder syntax for deref patterns"
)] )]
pub use crate::macros::builtin::deref; pub use crate::macros::builtin::deref;
#[unstable(
feature = "type_alias_impl_trait",
issue = "63063",
reason = "`type_alias_impl_trait` has open design concerns"
)]
#[cfg(not(bootstrap))]
pub use crate::macros::builtin::define_opaque;

View file

@ -432,6 +432,7 @@ mod helper {
use super::*; use super::*;
pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe; pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
#[cfg_attr(not(bootstrap), define_opaque(LazyResolve))]
pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve { pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve {
move || { move || {
// Use the global backtrace lock to synchronize this as it's a // Use the global backtrace lock to synchronize this as it's a

View file

@ -103,6 +103,15 @@ pub use core::prelude::v1::type_ascribe;
)] )]
pub use core::prelude::v1::deref; pub use core::prelude::v1::deref;
// Do not `doc(no_inline)` either.
#[unstable(
feature = "type_alias_impl_trait",
issue = "63063",
reason = "`type_alias_impl_trait` has open design concerns"
)]
#[cfg(not(bootstrap))]
pub use core::prelude::v1::define_opaque;
// The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated // The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated
// rather than glob imported because we want docs to show these re-exports as // rather than glob imported because we want docs to show these re-exports as
// pointing to within `std`. // pointing to within `std`.

View file

@ -272,7 +272,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
fn visit_item(&mut self, item: &'tcx Item<'tcx>) { fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
match item.kind { match item.kind {
ItemKind::Static(_, _, _) ItemKind::Static(..)
| ItemKind::Const(_, _, _) | ItemKind::Const(_, _, _)
| ItemKind::Fn { .. } | ItemKind::Fn { .. }
| ItemKind::Macro(_, _) | ItemKind::Macro(_, _)

View file

@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
generics: lg, generics: lg,
contract: lc, contract: lc,
body: lb, body: lb,
define_opaque: _,
}), }),
Fn(box ast::Fn { Fn(box ast::Fn {
defaultness: rd, defaultness: rd,
@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
generics: rg, generics: rg,
contract: rc, contract: rc,
body: rb, body: rb,
define_opaque: _,
}), }),
) => { ) => {
eq_defaultness(*ld, *rd) eq_defaultness(*ld, *rd)
@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
generics: lg, generics: lg,
contract: lc, contract: lc,
body: lb, body: lb,
define_opaque: _,
}), }),
Fn(box ast::Fn { Fn(box ast::Fn {
defaultness: rd, defaultness: rd,
@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
generics: rg, generics: rg,
contract: rc, contract: rc,
body: rb, body: rb,
define_opaque: _,
}), }),
) => { ) => {
eq_defaultness(*ld, *rd) eq_defaultness(*ld, *rd)
@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
generics: lg, generics: lg,
contract: lc, contract: lc,
body: lb, body: lb,
define_opaque: _,
}), }),
Fn(box ast::Fn { Fn(box ast::Fn {
defaultness: rd, defaultness: rd,
@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
generics: rg, generics: rg,
contract: rc, contract: rc,
body: rb, body: rb,
define_opaque: _,
}), }),
) => { ) => {
eq_defaultness(*ld, *rd) eq_defaultness(*ld, *rd)

View file

@ -1,10 +0,0 @@
//@ check-pass
// ICE: #10972
// asked to assemble constituent types of unexpected type: Binder(Foo, [])
#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
type Foo = impl Debug;
const FOO2: Foo = 22_u32;
pub fn main() {}

View file

@ -192,6 +192,7 @@ impl Atpit for () {
type Tait = impl DerefMut; type Tait = impl DerefMut;
//~^ implied_bounds_in_impls //~^ implied_bounds_in_impls
#[define_opaque(Tait)]
fn define() -> Tait { fn define() -> Tait {
&mut [] as &mut [()] &mut [] as &mut [()]
} }

View file

@ -192,6 +192,7 @@ impl Atpit for () {
type Tait = impl Deref + DerefMut; type Tait = impl Deref + DerefMut;
//~^ implied_bounds_in_impls //~^ implied_bounds_in_impls
#[define_opaque(Tait)]
fn define() -> Tait { fn define() -> Tait {
&mut [] as &mut [()] &mut [] as &mut [()]
} }

View file

@ -207,6 +207,7 @@ mod msrv {
mod with_ty_alias { mod with_ty_alias {
type Foo = impl std::fmt::Debug; type Foo = impl std::fmt::Debug;
#[define_opaque(Foo)]
fn foo(_: Foo) { fn foo(_: Foo) {
let _: Foo = 1; let _: Foo = 1;
} }

View file

@ -17,6 +17,7 @@ mod issue10041 {
struct Bomb2; struct Bomb2;
impl Bomb2 { impl Bomb2 {
#[define_opaque(X)]
pub fn new() -> X { pub fn new() -> X {
//~^ ERROR: overflow evaluating the requirement //~^ ERROR: overflow evaluating the requirement
0i32 0i32

View file

@ -1,5 +1,5 @@
error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X` error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X`
--> tests/ui/new_ret_no_self_overflow.rs:20:25 --> tests/ui/new_ret_no_self_overflow.rs:21:25
| |
LL | pub fn new() -> X { LL | pub fn new() -> X {
| ^ | ^

View file

@ -4058,7 +4058,6 @@ ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs
ui/type-alias-impl-trait/issue-101750.rs ui/type-alias-impl-trait/issue-101750.rs
ui/type-alias-impl-trait/issue-104817.rs ui/type-alias-impl-trait/issue-104817.rs
ui/type-alias-impl-trait/issue-109054.rs ui/type-alias-impl-trait/issue-109054.rs
ui/type-alias-impl-trait/issue-52843-closure-constrain.rs
ui/type-alias-impl-trait/issue-52843.rs ui/type-alias-impl-trait/issue-52843.rs
ui/type-alias-impl-trait/issue-53092-2.rs ui/type-alias-impl-trait/issue-53092-2.rs
ui/type-alias-impl-trait/issue-53092.rs ui/type-alias-impl-trait/issue-53092.rs

View file

@ -9,18 +9,16 @@
extern crate core; extern crate core;
mod defining_module { pub type Type1 = impl Send;
pub type Type1 = impl Send;
pub fn foo() #[define_opaque(Type1)]
where pub fn foo()
Type1: 'static, where
{ Type1: 'static,
pub struct Foo<T, const N: usize>([T; N]); {
let _: Type1 = Foo([0; 32]); pub struct Foo<T, const N: usize>([T; N]);
} let _: Type1 = Foo([0; 32]);
} }
use defining_module::*;
pub fn foo1(_: Type1) {} pub fn foo1(_: Type1) {}
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
@ -29,6 +27,6 @@ pub fn foo2(_: Type1, _: Type1) {}
pub fn foo3(_: Type1, _: Type1, _: Type1) {} pub fn foo3(_: Type1, _: Type1, _: Type1) {}
// CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo3FooIu3i32Lu5usize32EEE"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EEE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo3FooIu3i32Lu5usize32EES2_E"} // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_E"}
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo3FooIu3i32Lu5usize32EES2_S2_E"} // CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_S2_E"}

View file

@ -9,22 +9,18 @@
extern crate core; extern crate core;
mod defining_module { pub type Type1 = impl Send;
pub type Type1 = impl Send; #[define_opaque(Type1)]
pub fn foo<'a>()
pub fn foo<'a>() where
where Type1: 'static,
Type1: 'static, {
{ pub struct Foo<'a>(&'a i32);
pub struct Foo<'a>(&'a i32); pub struct Bar<'a, 'b>(&'a i32, &'b Foo<'b>);
pub struct Bar<'a, 'b>(&'a i32, &'b Foo<'b>); let _: Type1 = Bar;
let _: Type1 = Bar;
}
} }
use defining_module::*;
pub fn foo1(_: Type1) {} pub fn foo1(_: Type1) {}
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo2(_: Type1, _: Type1) {} pub fn foo2(_: Type1, _: Type1) {}

View file

@ -9,47 +9,41 @@
extern crate core; extern crate core;
mod defining_module { pub type Type1 = impl Send;
pub type Type1 = impl Send; pub type Type2 = impl Send;
pub type Type2 = impl Send; pub type Type3 = impl Send;
pub type Type3 = impl Send; pub type Type4 = impl Send;
pub type Type4 = impl Send;
pub fn foo() #[define_opaque(Type1, Type2, Type4)]
where pub fn foo() {
Type1: 'static, // Type in extern path
Type2: 'static, extern "C" {
Type4: 'static, fn bar();
{
// Type in extern path
extern "C" {
fn bar();
}
let _: Type1 = bar;
// Type in closure path
|| {
pub struct Foo;
let _: Type2 = Foo;
};
// Type in const path
const {
pub struct Foo;
fn bar() -> Type3 {
Foo
}
};
// Type in impl path
struct Foo;
impl Foo {
fn bar(&self) {}
}
let _: Type4 = <Foo>::bar;
} }
let _: Type1 = bar;
// Type in closure path
|| {
pub struct Foo;
let _: Type2 = Foo;
};
// Type in const path
const {
pub struct Foo;
#[define_opaque(Type3)]
fn bar() -> Type3 {
Foo
}
};
// Type in impl path
struct Foo;
impl Foo {
fn bar(&self) {}
}
let _: Type4 = <Foo>::bar;
} }
use defining_module::*;
// Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore // Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore
@ -78,15 +72,15 @@ pub fn foo11(_: &Type4, _: &Type4) {}
pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {} pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {}
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"} // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"} // CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"}
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"} // CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"} // CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"} // CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"} // CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"} // CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"} // CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"} // CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"} // CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"} // CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}

View file

@ -6,6 +6,7 @@
struct Bug { struct Bug {
V1: [(); { V1: [(); {
type F = impl std::future::Future<Output = impl Sized>; type F = impl std::future::Future<Output = impl Sized>;
#[define_opaque(F)]
fn concrete_use() -> F { fn concrete_use() -> F {
//~^ ERROR to be a future that resolves to `u8`, but it resolves to `()` //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()`
async {} async {}

View file

@ -6,10 +6,12 @@ type Alias<'a> = impl T;
struct S; struct S;
impl<'a> T for &'a S {} impl<'a> T for &'a S {}
#[define_opaque(Alias)]
fn with_positive(fun: impl Fn(Alias<'_>)) { fn with_positive(fun: impl Fn(Alias<'_>)) {
with_positive(|&n| ()); with_positive(|&n| ());
} }
#[define_opaque(Alias)]
fn main(Alias<'_>) { fn main(Alias<'_>) {
with_positive(|&a| ()); with_positive(|&a| ());
} }

View file

@ -6,6 +6,7 @@ type Alias<'a> = impl T;
struct S; struct S;
impl<'a> T for &'a S {} impl<'a> T for &'a S {}
#[define_opaque(Alias)]
fn with_positive(fun: impl Fn(Alias<'_>)) { fn with_positive(fun: impl Fn(Alias<'_>)) {
with_positive(|&n| ()); with_positive(|&n| ());
} }

View file

@ -1,16 +1,26 @@
//@ known-bug: rust-lang/rust#125185 //@ known-bug: rust-lang/rust#125185
//@ compile-flags: -Zvalidate-mir //@ compile-flags: -Zvalidate-mir
#![feature(type_alias_impl_trait)]
type Foo = impl Send; type Foo = impl Send;
struct A; struct A;
const VALUE: Foo = value(); #[define_opaque(Foo)]
const fn foo() -> Foo {
value()
}
fn test(foo: Foo<'a>, f: impl for<'b> FnMut()) { const VALUE: Foo = foo();
#[define_opaque(Foo)]
fn test(foo: Foo, f: impl for<'b> FnMut()) {
match VALUE { match VALUE {
0 | 0 => {} 0 | 0 => {}
_ => (), _ => (),
} }
} }
fn main() {}

View file

@ -8,14 +8,18 @@ use std::path::Path;
struct A { struct A {
pub func: fn(check: Bar, b: Option<&Path>), pub func: fn(check: Bar, b: Option<&Path>),
} }
const MY_A: A = A {
func: |check, b| { #[define_opaque(Bar)]
if check { fn foo() -> A {
() A {
} else if let Some(_) = b.and_then(|p| p.parent()) { func: |check, b| {
() if check {
} ()
}, } else if let Some(_) = b.and_then(|p| p.parent()) {
}; ()
}
},
}
}
fn main() {} fn main() {}

View file

@ -1,12 +0,0 @@
//@ known-bug: #131298
fn dyn_hoops<T>() -> *const dyn Iterator<Item = impl Captures> {
loop {}
}
mod typeck {
type Opaque = impl Sized;
fn define() -> Opaque {
let _: Opaque = super::dyn_hoops::<u8>();
}
}

View file

@ -1,5 +1,5 @@
//@ known-bug: #131886 //@ known-bug: #131886
//@ compile-flags: -Zvalidate-mir --crate-type=lib //@ compile-flags: -Zvalidate-mir
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
type Tait = impl Sized; type Tait = impl Sized;
@ -7,6 +7,9 @@ type Tait = impl Sized;
trait Foo<'a>: Bar<'a, 'a, Tait> {} trait Foo<'a>: Bar<'a, 'a, Tait> {}
trait Bar<'a, 'b, T> {} trait Bar<'a, 'b, T> {}
#[define_opaque(Tait)]
fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) { fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
let _ = x as &dyn Bar<'_, '_, ()>; let _ = x as &dyn Bar<'_, '_, ()>;
} }
fn main() {}

View file

@ -7,10 +7,12 @@ fn set(x: &isize) -> isize {
*x *x
} }
#[define_opaque(Tait)]
fn d(x: Tait) { fn d(x: Tait) {
set(x); set(x);
} }
#[define_opaque(Tait)]
fn other_define() -> Tait { fn other_define() -> Tait {
() ()
} }

View file

@ -22,6 +22,7 @@ impl<T: Project1<Assoc1 = ()>> Project2 for PhantomData<T> {
type Alias<T> = impl Project2; type Alias<T> = impl Project2;
#[define_opaque(Alias)]
fn constrain<T>() -> Alias<T> { fn constrain<T>() -> Alias<T> {
PhantomData::<T> PhantomData::<T>
} }

View file

@ -11,7 +11,8 @@ impl Foo<i32> {
type Tait = impl Sized; type Tait = impl Sized;
fn bar(_: Tait) { #[define_opaque(Tait)]
fn bar() {
let x: Foo<Tait>::Assoc = 42; let x: Foo<Tait>::Assoc = 42;
} }

View file

@ -29,7 +29,7 @@ error: unconstrained opaque type
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor; LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `X` must be used in combination with a concrete type within the same module = note: `X` must be used in combination with a concrete type within the same crate
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -11,10 +11,8 @@ impl<T> IsPtr for T {
type Tait = impl IsPtr<Assoc: Fn(i32)> + Fn(u32); type Tait = impl IsPtr<Assoc: Fn(i32)> + Fn(u32);
fn hello() #[define_opaque(Tait)]
where fn hello() {
Tait:,
{
let _: Tait = |x| {}; let _: Tait = |x| {};
} }

View file

@ -179,19 +179,25 @@ where
type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR unconstrained opaque type
type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR unconstrained opaque type
type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR unconstrained opaque type
type ETAI4 = impl Iterator<Item: Copy, Item: Send>; type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR unconstrained opaque type
type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR unconstrained opaque type
type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
//~| ERROR unconstrained opaque type
trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]

View file

@ -325,7 +325,7 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:182:36 --> $DIR/duplicate.rs:183:36
| |
LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -333,7 +333,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:184:39 --> $DIR/duplicate.rs:186:39
| |
LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -341,7 +341,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:186:40 --> $DIR/duplicate.rs:189:40
| |
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -349,7 +349,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:186:40 --> $DIR/duplicate.rs:189:40
| |
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -359,7 +359,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:189:40 --> $DIR/duplicate.rs:193:40
| |
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -367,7 +367,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:189:40 --> $DIR/duplicate.rs:193:40
| |
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -377,7 +377,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:192:43 --> $DIR/duplicate.rs:197:43
| |
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -385,7 +385,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:192:43 --> $DIR/duplicate.rs:197:43
| |
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -395,7 +395,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:196:36 --> $DIR/duplicate.rs:202:36
| |
LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -403,7 +403,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:198:36 --> $DIR/duplicate.rs:204:36
| |
LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -411,7 +411,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:200:39 --> $DIR/duplicate.rs:206:39
| |
LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -419,7 +419,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:202:34 --> $DIR/duplicate.rs:208:34
| |
LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -427,7 +427,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:202:34 --> $DIR/duplicate.rs:208:34
| |
LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -437,7 +437,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:202:34 --> $DIR/duplicate.rs:208:34
| |
LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -447,7 +447,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:206:34 --> $DIR/duplicate.rs:212:34
| |
LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -455,7 +455,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:206:34 --> $DIR/duplicate.rs:212:34
| |
LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -465,7 +465,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:206:34 --> $DIR/duplicate.rs:212:34
| |
LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -475,7 +475,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:210:37 --> $DIR/duplicate.rs:216:37
| |
LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -483,7 +483,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:210:37 --> $DIR/duplicate.rs:216:37
| |
LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -493,7 +493,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:210:37 --> $DIR/duplicate.rs:216:37
| |
LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -503,7 +503,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:216:29 --> $DIR/duplicate.rs:222:29
| |
LL | T: Iterator<Item: Copy, Item: Send>, LL | T: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -511,7 +511,7 @@ LL | T: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:222:29 --> $DIR/duplicate.rs:228:29
| |
LL | T: Iterator<Item: Copy, Item: Copy>, LL | T: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -519,7 +519,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:228:32 --> $DIR/duplicate.rs:234:32
| |
LL | T: Iterator<Item: 'static, Item: 'static>, LL | T: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -527,7 +527,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:234:32 --> $DIR/duplicate.rs:240:32
| |
LL | Self: Iterator<Item: Copy, Item: Send>, LL | Self: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -535,7 +535,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:234:32 --> $DIR/duplicate.rs:240:32
| |
LL | Self: Iterator<Item: Copy, Item: Send>, LL | Self: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -545,7 +545,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:234:32 --> $DIR/duplicate.rs:240:32
| |
LL | Self: Iterator<Item: Copy, Item: Send>, LL | Self: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -555,7 +555,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:242:32 --> $DIR/duplicate.rs:248:32
| |
LL | Self: Iterator<Item: Copy, Item: Copy>, LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -563,7 +563,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:242:32 --> $DIR/duplicate.rs:248:32
| |
LL | Self: Iterator<Item: Copy, Item: Copy>, LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -573,7 +573,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:242:32 --> $DIR/duplicate.rs:248:32
| |
LL | Self: Iterator<Item: Copy, Item: Copy>, LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -583,7 +583,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:250:35 --> $DIR/duplicate.rs:256:35
| |
LL | Self: Iterator<Item: 'static, Item: 'static>, LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -591,7 +591,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:250:35 --> $DIR/duplicate.rs:256:35
| |
LL | Self: Iterator<Item: 'static, Item: 'static>, LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -601,7 +601,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:250:35 --> $DIR/duplicate.rs:256:35
| |
LL | Self: Iterator<Item: 'static, Item: 'static>, LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -611,7 +611,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:257:34 --> $DIR/duplicate.rs:263:34
| |
LL | type A: Iterator<Item: Copy, Item: Send>; LL | type A: Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -619,7 +619,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:257:34 --> $DIR/duplicate.rs:263:34
| |
LL | type A: Iterator<Item: Copy, Item: Send>; LL | type A: Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -629,7 +629,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>;
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:262:34 --> $DIR/duplicate.rs:268:34
| |
LL | type A: Iterator<Item: Copy, Item: Copy>; LL | type A: Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -637,7 +637,7 @@ LL | type A: Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:262:34 --> $DIR/duplicate.rs:268:34
| |
LL | type A: Iterator<Item: Copy, Item: Copy>; LL | type A: Iterator<Item: Copy, Item: Copy>;
| ---------- ^^^^^^^^^^ re-bound here | ---------- ^^^^^^^^^^ re-bound here
@ -647,7 +647,7 @@ LL | type A: Iterator<Item: Copy, Item: Copy>;
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:267:37 --> $DIR/duplicate.rs:273:37
| |
LL | type A: Iterator<Item: 'static, Item: 'static>; LL | type A: Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -655,7 +655,7 @@ LL | type A: Iterator<Item: 'static, Item: 'static>;
| `Item` bound here first | `Item` bound here first
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate.rs:267:37 --> $DIR/duplicate.rs:273:37
| |
LL | type A: Iterator<Item: 'static, Item: 'static>; LL | type A: Iterator<Item: 'static, Item: 'static>;
| ------------- ^^^^^^^^^^^^^ re-bound here | ------------- ^^^^^^^^^^^^^ re-bound here
@ -697,7 +697,55 @@ help: consider specifying the generic argument
LL | iter::empty::<T>() LL | iter::empty::<T>()
| +++++ | +++++
error: aborting due to 81 previous errors error: unconstrained opaque type
--> $DIR/duplicate.rs:180:51
|
LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
| ^^^^^^^^^
|
= note: `ETAI1` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/duplicate.rs:183:51
|
LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
| ^^^^^^^^^
|
= note: `ETAI2` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/duplicate.rs:186:57
|
LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| ^^^^^^^^^
|
= note: `ETAI3` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/duplicate.rs:189:14
|
LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `ETAI4` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/duplicate.rs:193:14
|
LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `ETAI5` must be used in combination with a concrete type within the same crate
error: unconstrained opaque type
--> $DIR/duplicate.rs:197:14
|
LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `ETAI6` must be used in combination with a concrete type within the same crate
error: aborting due to 87 previous errors
Some errors have detailed explanations: E0282, E0719. Some errors have detailed explanations: E0282, E0719.
For more information about an error, try `rustc --explain E0282`. For more information about an error, try `rustc --explain E0282`.

View file

@ -31,6 +31,7 @@ impl Tr1 for S1 {
} }
type Et1 = impl Tr1<As1: Copy>; type Et1 = impl Tr1<As1: Copy>;
#[define_opaque(Et1)]
fn def_et1() -> Et1 { fn def_et1() -> Et1 {
S1 S1
} }
@ -39,6 +40,7 @@ pub fn use_et1() {
} }
type Et2 = impl Tr1<As1: 'static>; type Et2 = impl Tr1<As1: 'static>;
#[define_opaque(Et2)]
fn def_et2() -> Et2 { fn def_et2() -> Et2 {
S1 S1
} }
@ -47,6 +49,7 @@ pub fn use_et2() {
} }
type Et3 = impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>; type Et3 = impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>;
#[define_opaque(Et3)]
fn def_et3() -> Et3 { fn def_et3() -> Et3 {
struct A; struct A;
impl Tr1 for A { impl Tr1 for A {
@ -68,6 +71,7 @@ pub fn use_et3() {
} }
type Et4 = impl Tr1<As1: for<'a> Tr2<'a>>; type Et4 = impl Tr1<As1: for<'a> Tr2<'a>>;
#[define_opaque(Et4)]
fn def_et4() -> Et4 { fn def_et4() -> Et4 {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct A; struct A;

View file

@ -4,11 +4,14 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
type Tait = impl AsyncFn(); type Tait = impl AsyncFn();
#[define_opaque(Tait)]
fn tait() -> Tait { fn tait() -> Tait {
|| async {} || async {}
} }
fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x } fn foo(x: impl AsyncFn()) -> impl AsyncFn() {
x
}
fn param<T: AsyncFn()>() {} fn param<T: AsyncFn()>() {}

View file

@ -11,15 +11,17 @@ pub type Func = impl Sized;
// Late bound region should be allowed to escape the function, since it's bound // Late bound region should be allowed to escape the function, since it's bound
// in the type. // in the type.
#[define_opaque(Func)]
fn null_function_ptr() -> Func { fn null_function_ptr() -> Func {
None::<for<'a> fn(&'a ())> None::<for<'a> fn(&'a ())>
} }
async fn async_nop(_: &u8) {} async fn async_nop(_: &u8) {}
pub type ServeFut = impl Future<Output=()>; pub type ServeFut = impl Future<Output = ()>;
// Late bound regions occur in the coroutine witness type here. // Late bound regions occur in the coroutine witness type here.
#[define_opaque(ServeFut)]
fn serve() -> ServeFut { fn serve() -> ServeFut {
async move { async move {
let x = 5; let x = 5;

View file

@ -13,6 +13,7 @@ pub trait Trait {}
pub type TAIT<T> = impl Trait; pub type TAIT<T> = impl Trait;
#[define_opaque(TAIT)]
async fn foo<T>() -> TAIT<T> { async fn foo<T>() -> TAIT<T> {
Foo Foo
} }

View file

@ -24,15 +24,15 @@ const BAR: u32 = 3;
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
fn foo() { fn foo() {
let _ = #[collapse_debuginfo(yes)] || { }; let _ = #[collapse_debuginfo(yes)] || { };
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
let _ = 3; let _ = 3;
let _ = #[collapse_debuginfo(yes)] 3; let _ = #[collapse_debuginfo(yes)] 3;
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
match (3, 4) { match (3, 4) {
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
_ => (), _ => (),
} }
} }
@ -50,7 +50,7 @@ type Map = HashMap<u32, u32>;
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
enum Foo { enum Foo {
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
Variant, Variant,
} }
@ -58,7 +58,7 @@ enum Foo {
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
struct Bar { struct Bar {
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
field: u32, field: u32,
} }
@ -73,7 +73,7 @@ union Qux {
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
trait Foobar { trait Foobar {
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
type Bar; type Bar;
} }
@ -85,6 +85,7 @@ impl Foobar for Bar {
type Bar = u32; type Bar = u32;
} }
#[define_opaque(AFoobar)]
fn constraining() -> AFoobar { fn constraining() -> AFoobar {
Bar { field: 3 } Bar { field: 3 }
} }
@ -93,11 +94,11 @@ fn constraining() -> AFoobar {
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
impl Bar { impl Bar {
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
const FOO: u32 = 3; const FOO: u32 = 3;
#[collapse_debuginfo(yes)] #[collapse_debuginfo(yes)]
//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
fn bar(&self) {} fn bar(&self) {}
} }

View file

@ -176,7 +176,7 @@ LL | type AFoobar = impl Foobar;
| --------------------------- not a macro definition | --------------------------- not a macro definition
error: `collapse_debuginfo` attribute should be applied to macro definitions error: `collapse_debuginfo` attribute should be applied to macro definitions
--> $DIR/collapse-debuginfo-invalid.rs:92:1 --> $DIR/collapse-debuginfo-invalid.rs:93:1
| |
LL | #[collapse_debuginfo(yes)] LL | #[collapse_debuginfo(yes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -200,7 +200,7 @@ LL | type Bar;
| --------- not a macro definition | --------- not a macro definition
error: `collapse_debuginfo` attribute should be applied to macro definitions error: `collapse_debuginfo` attribute should be applied to macro definitions
--> $DIR/collapse-debuginfo-invalid.rs:95:5 --> $DIR/collapse-debuginfo-invalid.rs:96:5
| |
LL | #[collapse_debuginfo(yes)] LL | #[collapse_debuginfo(yes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -209,7 +209,7 @@ LL | const FOO: u32 = 3;
| ------------------- not a macro definition | ------------------- not a macro definition
error: `collapse_debuginfo` attribute should be applied to macro definitions error: `collapse_debuginfo` attribute should be applied to macro definitions
--> $DIR/collapse-debuginfo-invalid.rs:99:5 --> $DIR/collapse-debuginfo-invalid.rs:100:5
| |
LL | #[collapse_debuginfo(yes)] LL | #[collapse_debuginfo(yes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -6,6 +6,7 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
type Opaque2<'a> = impl Sized + 'a; type Opaque2<'a> = impl Sized + 'a;
#[define_opaque(Opaque2)]
fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'a>) { fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'a>) {
|x| x |x| x
//~^ ERROR lifetime may not live long enough //~^ ERROR lifetime may not live long enough

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/overwrite-anon-late-param-regions.rs:10:9 --> $DIR/overwrite-anon-late-param-regions.rs:11:9
| |
LL | |x| x LL | |x| x
| - ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | - ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@ -8,7 +8,7 @@ LL | |x| x
| has type `(&'2 str, &str)` | has type `(&'2 str, &str)`
error[E0792]: expected generic lifetime parameter, found `'a` error[E0792]: expected generic lifetime parameter, found `'a`
--> $DIR/overwrite-anon-late-param-regions.rs:10:5 --> $DIR/overwrite-anon-late-param-regions.rs:11:5
| |
LL | type Opaque2<'a> = impl Sized + 'a; LL | type Opaque2<'a> = impl Sized + 'a;
| -- this generic parameter must be used with a generic lifetime parameter | -- this generic parameter must be used with a generic lifetime parameter

View file

@ -1,6 +1,7 @@
// Test that encountering closures during coherence does not cause issues. // Test that encountering closures during coherence does not cause issues.
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
type OpaqueClosure = impl Sized; type OpaqueClosure = impl Sized;
#[define_opaque(OpaqueClosure)]
fn defining_use() -> OpaqueClosure { fn defining_use() -> OpaqueClosure {
|| () || ()
} }

View file

@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>` error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
--> $DIR/coherence-with-closure.rs:11:1 --> $DIR/coherence-with-closure.rs:12:1
| |
LL | impl Trait for Wrapper<OpaqueClosure> {} LL | impl Trait for Wrapper<OpaqueClosure> {}
| ------------------------------------- first implementation here | ------------------------------------- first implementation here

View file

@ -7,6 +7,7 @@
//@ [specialized]check-pass //@ [specialized]check-pass
type OpaqueCoroutine = impl Sized; type OpaqueCoroutine = impl Sized;
#[define_opaque(OpaqueCoroutine)]
fn defining_use() -> OpaqueCoroutine { fn defining_use() -> OpaqueCoroutine {
#[coroutine] #[coroutine]
|| { || {

View file

@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>` error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
--> $DIR/coherence-with-coroutine.rs:22:1 --> $DIR/coherence-with-coroutine.rs:23:1
| |
LL | impl Trait for Wrapper<OpaqueCoroutine> {} LL | impl Trait for Wrapper<OpaqueCoroutine> {}
| --------------------------------------- first implementation here | --------------------------------------- first implementation here

View file

@ -8,6 +8,7 @@ struct Outer<T: ?Sized> {
type InnerSend<T: ?Sized> = impl Send; type InnerSend<T: ?Sized> = impl Send;
#[define_opaque(InnerSend)]
fn constrain<T: ?Sized>() -> InnerSend<T> { fn constrain<T: ?Sized>() -> InnerSend<T> {
() ()
} }

View file

@ -8,6 +8,7 @@ struct Send<T> {
type InnerSend<T> = impl Sized; type InnerSend<T> = impl Sized;
#[define_opaque(InnerSend)]
fn constrain<T>() -> InnerSend<T> { fn constrain<T>() -> InnerSend<T> {
() ()
} }

View file

@ -1,11 +1,11 @@
error[E0119]: conflicting implementations of trait `Trait<_>` error[E0119]: conflicting implementations of trait `Trait<_>`
--> $DIR/opaques.rs:28:1 --> $DIR/opaques.rs:27:1
| |
LL | impl<T> Trait<T> for T { LL | impl<T> Trait<T> for T {
| ---------------------- first implementation here | ---------------------- first implementation here
... ...
LL | impl<T> Trait<T> for defining_scope::Alias<T> { LL | impl<T> Trait<T> for Alias<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,17 +1,17 @@
error[E0119]: conflicting implementations of trait `Trait<_>` error[E0119]: conflicting implementations of trait `Trait<_>`
--> $DIR/opaques.rs:28:1 --> $DIR/opaques.rs:27:1
| |
LL | impl<T> Trait<T> for T { LL | impl<T> Trait<T> for T {
| ---------------------- first implementation here | ---------------------- first implementation here
... ...
LL | impl<T> Trait<T> for defining_scope::Alias<T> { LL | impl<T> Trait<T> for Alias<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/opaques.rs:11:23 --> $DIR/opaques.rs:11:19
| |
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> { LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -4,14 +4,13 @@
// A regression test for #105787 // A regression test for #105787
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
mod defining_scope {
use super::*;
pub type Alias<T> = impl Sized;
pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> { pub type Alias<T> = impl Sized;
//[next]~^ ERROR type annotations needed
x #[define_opaque(Alias)]
} pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
//[next]~^ ERROR type annotations needed
x
} }
struct Container<T: Trait<U>, U> { struct Container<T: Trait<U>, U> {
@ -25,12 +24,12 @@ trait Trait<T> {
impl<T> Trait<T> for T { impl<T> Trait<T> for T {
type Assoc = Box<u32>; type Assoc = Box<u32>;
} }
impl<T> Trait<T> for defining_scope::Alias<T> { impl<T> Trait<T> for Alias<T> {
//~^ ERROR conflicting implementations of trait //~^ ERROR conflicting implementations of trait
type Assoc = usize; type Assoc = usize;
} }
fn main() { fn main() {
let x: Box<u32> = defining_scope::cast::<()>(Container { x: 0 }).x; let x: Box<u32> = cast::<()>(Container { x: 0 }).x;
println!("{}", *x); println!("{}", *x);
} }

View file

@ -7,6 +7,7 @@
type Identity<T> = impl Sized; type Identity<T> = impl Sized;
#[define_opaque(Identity)]
fn define_identity<T>(x: T) -> Identity<T> { fn define_identity<T>(x: T) -> Identity<T> {
x x
} }
@ -16,6 +17,7 @@ impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
type Opaque<T> = impl Sized; type Opaque<T> = impl Sized;
#[define_opaque(Opaque)]
fn define_local<T>() -> Opaque<T> { fn define_local<T>() -> Opaque<T> {
Local Local
} }

View file

@ -1,5 +1,5 @@
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/orphan-check-opaque-types-not-covering.rs:14:6 --> $DIR/orphan-check-opaque-types-not-covering.rs:15:6
| |
LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {} LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
@ -8,7 +8,7 @@ LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/orphan-check-opaque-types-not-covering.rs:23:6 --> $DIR/orphan-check-opaque-types-not-covering.rs:25:6
| |
LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {} LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)

View file

@ -3,14 +3,14 @@
type Foo = impl Sized; type Foo = impl Sized;
fn with_bound<const N: usize>() -> Foo #[define_opaque(Foo)]
fn with_bound<const N: usize>()
where where
[u8; (N / 2) as usize]: Sized, [u8; (N / 2) as usize]: Sized,
{ {
let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize]; let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| ERROR non-primitive cast: `usize` as `Foo` //~| ERROR non-primitive cast: `usize` as `Foo`
todo!()
} }
fn main() { fn main() {

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/opaque_type.rs:10:17 --> $DIR/opaque_type.rs:11:17
| |
LL | type Foo = impl Sized; LL | type Foo = impl Sized;
| ---------- the found opaque type | ---------- the found opaque type
@ -11,7 +11,7 @@ LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
found opaque type `Foo` found opaque type `Foo`
error[E0605]: non-primitive cast: `usize` as `Foo` error[E0605]: non-primitive cast: `usize` as `Foo`
--> $DIR/opaque_type.rs:10:17 --> $DIR/opaque_type.rs:11:17
| |
LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize]; LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
| ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object | ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object

View file

@ -1,9 +1,8 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
type Foo = impl Sized; type Foo = impl Sized;
//~^ ERROR: cycle
//~| ERROR: cycle
#[define_opaque(Foo)]
fn foo<const C: Foo>() {} fn foo<const C: Foo>() {}
//~^ ERROR: `Foo` is forbidden as the type of a const generic parameter //~^ ERROR: `Foo` is forbidden as the type of a const generic parameter
//~| ERROR: item does not constrain //~| ERROR: item does not constrain

View file

@ -1,26 +1,26 @@
error: `Foo` is forbidden as the type of a const generic parameter error: `Foo` is forbidden as the type of a const generic parameter
--> $DIR/opaque_types.rs:7:17 --> $DIR/opaque_types.rs:6:17
| |
LL | fn foo<const C: Foo>() {} LL | fn foo<const C: Foo>() {}
| ^^^ | ^^^
| |
= note: the only supported types are integers, `bool`, and `char` = note: the only supported types are integers, `bool`, and `char`
error: item does not constrain `Foo::{opaque#0}`, but has it in its signature error: item does not constrain `Foo::{opaque#0}`
--> $DIR/opaque_types.rs:7:4 --> $DIR/opaque_types.rs:6:4
| |
LL | fn foo<const C: Foo>() {} LL | fn foo<const C: Foo>() {}
| ^^^ | ^^^
| |
= note: consider moving the opaque type's declaration and defining uses into a separate module = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is in the signature note: this opaque type is supposed to be constrained
--> $DIR/opaque_types.rs:3:12 --> $DIR/opaque_types.rs:3:12
| |
LL | type Foo = impl Sized; LL | type Foo = impl Sized;
| ^^^^^^^^^^ | ^^^^^^^^^^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/opaque_types.rs:12:11 --> $DIR/opaque_types.rs:11:11
| |
LL | type Foo = impl Sized; LL | type Foo = impl Sized;
| ---------- the expected opaque type | ---------- the expected opaque type
@ -31,106 +31,6 @@ LL | foo::<42>();
= note: expected opaque type `Foo` = note: expected opaque type `Foo`
found type `{integer}` found type `{integer}`
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` error: aborting due to 3 previous errors
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires computing type of opaque `Foo::{opaque#0}`...
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
note: ...which requires type-checking `main`...
--> $DIR/opaque_types.rs:11:1
|
LL | fn main() {
| ^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires const-evaluating + checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires caching mir of `main::{constant#0}` for CTFE...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires elaborating drops for `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
= note: ...which requires normalizing `Foo`...
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
note: cycle used when checking that `Foo::{opaque#0}` is well-formed
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}` For more information about this error, try `rustc --explain E0308`.
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires type-checking `main`...
--> $DIR/opaque_types.rs:11:1
|
LL | fn main() {
| ^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires const-evaluating + checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires caching mir of `main::{constant#0}` for CTFE...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires elaborating drops for `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires borrow-checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires promoting constants in MIR for `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
note: ...which requires const checking `main::{constant#0}`...
--> $DIR/opaque_types.rs:12:11
|
LL | foo::<42>();
| ^^
= note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
note: cycle used when computing type of `Foo::{opaque#0}`
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0308, E0391.
For more information about an error, try `rustc --explain E0308`.

View file

@ -4,13 +4,14 @@ type Foo = impl Sized;
fn foo<const C: u32>() {} fn foo<const C: u32>() {}
const C: Foo = 42; #[define_opaque(Foo)]
const fn baz() -> Foo {
42
}
fn bar() #[define_opaque(Foo)]
where fn bar() {
Foo:, foo::<{ baz() }>();
{
foo::<C>();
//~^ ERROR: mismatched types //~^ ERROR: mismatched types
} }

View file

@ -1,11 +1,11 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/opaque_types2.rs:13:11 --> $DIR/opaque_types2.rs:14:13
| |
LL | type Foo = impl Sized; LL | type Foo = impl Sized;
| ---------- the found opaque type | ---------- the found opaque type
... ...
LL | foo::<C>(); LL | foo::<{ baz() }>();
| ^ expected `u32`, found opaque type | ^^^^^ expected `u32`, found opaque type
| |
= note: expected type `u32` = note: expected type `u32`
found opaque type `Foo` found opaque type `Foo`

View file

@ -3,14 +3,20 @@ type Foo = impl Send;
struct A; struct A;
const VALUE: Foo = value(); #[define_opaque(Foo)]
//~^ ERROR cannot find function `value` in this scope //~^ ERROR unstable library feature
const fn foo() -> Foo {
value()
//~^ ERROR cannot find function `value` in this scope
}
const VALUE: Foo = foo();
fn test() { fn test() {
match VALUE { match VALUE {
0 | 0 => {} 0 | 0 => {}
//~^ ERROR mismatched types //~^ ERROR mismatched types
//~| ERROR mismatched types //~| ERROR mismatched types
_ => (), _ => (),
} }
} }

View file

@ -1,3 +1,13 @@
error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
--> $DIR/ice-unhandled-type-122191.rs:6:3
|
LL | #[define_opaque(Foo)]
| ^^^^^^^^^^^^^
|
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: `impl Trait` in type aliases is unstable error[E0658]: `impl Trait` in type aliases is unstable
--> $DIR/ice-unhandled-type-122191.rs:1:12 --> $DIR/ice-unhandled-type-122191.rs:1:12
| |
@ -9,13 +19,16 @@ LL | type Foo = impl Send;
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0425]: cannot find function `value` in this scope error[E0425]: cannot find function `value` in this scope
--> $DIR/ice-unhandled-type-122191.rs:6:20 --> $DIR/ice-unhandled-type-122191.rs:9:5
| |
LL | const VALUE: Foo = value(); LL | value()
| ^^^^^ not found in this scope | ^^^^^ help: a constant with a similar name exists: `VALUE`
...
LL | const VALUE: Foo = foo();
| ------------------------- similarly named constant `VALUE` defined here
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/ice-unhandled-type-122191.rs:11:9 --> $DIR/ice-unhandled-type-122191.rs:17:9
| |
LL | type Foo = impl Send; LL | type Foo = impl Send;
| --------- the expected opaque type | --------- the expected opaque type
@ -27,14 +40,14 @@ LL | 0 | 0 => {}
| |
= note: expected opaque type `Foo` = note: expected opaque type `Foo`
found type `{integer}` found type `{integer}`
note: this item must have the opaque type in its signature in order to be able to register hidden types note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
--> $DIR/ice-unhandled-type-122191.rs:9:4 --> $DIR/ice-unhandled-type-122191.rs:15:4
| |
LL | fn test() { LL | fn test() {
| ^^^^ | ^^^^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/ice-unhandled-type-122191.rs:11:13 --> $DIR/ice-unhandled-type-122191.rs:17:13
| |
LL | type Foo = impl Send; LL | type Foo = impl Send;
| --------- the expected opaque type | --------- the expected opaque type
@ -46,13 +59,13 @@ LL | 0 | 0 => {}
| |
= note: expected opaque type `Foo` = note: expected opaque type `Foo`
found type `{integer}` found type `{integer}`
note: this item must have the opaque type in its signature in order to be able to register hidden types note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
--> $DIR/ice-unhandled-type-122191.rs:9:4 --> $DIR/ice-unhandled-type-122191.rs:15:4
| |
LL | fn test() { LL | fn test() {
| ^^^^ | ^^^^
error: aborting due to 4 previous errors error: aborting due to 5 previous errors
Some errors have detailed explanations: E0308, E0425, E0658. Some errors have detailed explanations: E0308, E0425, E0658.
For more information about an error, try `rustc --explain E0308`. For more information about an error, try `rustc --explain E0308`.

View file

@ -1,5 +1,5 @@
error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time error[E0493]: destructor of `Foo` cannot be evaluated at compile-time
--> $DIR/const-promoted-opaque.rs:28:26 --> $DIR/const-promoted-opaque.rs:32:26
| |
LL | let _: &'static _ = &FOO; LL | let _: &'static _ = &FOO;
| ^^^ the destructor for this type cannot be evaluated in constants | ^^^ the destructor for this type cannot be evaluated in constants
@ -8,13 +8,13 @@ LL | };
| - value is dropped here | - value is dropped here
error[E0492]: constants cannot refer to interior mutable data error[E0492]: constants cannot refer to interior mutable data
--> $DIR/const-promoted-opaque.rs:32:19 --> $DIR/const-promoted-opaque.rs:36:19
| |
LL | const BAZ: &Foo = &FOO; LL | const BAZ: &Foo = &FOO;
| ^^^^ this borrow of an interior mutable value may end up in the final value | ^^^^ this borrow of an interior mutable value may end up in the final value
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/const-promoted-opaque.rs:36:26 --> $DIR/const-promoted-opaque.rs:40:26
| |
LL | let _: &'static _ = &FOO; LL | let _: &'static _ = &FOO;
| ---------- ^^^ creates a temporary value which is freed while still in use | ---------- ^^^ creates a temporary value which is freed while still in use

View file

@ -8,25 +8,29 @@
//! hidden type of the opaque type. Thus we ended up relying on the //! hidden type of the opaque type. Thus we ended up relying on the
//! result of our analysis to compute the result of our analysis. //! result of our analysis to compute the result of our analysis.
//@[unit] check-pass pub type Foo = impl Sized;
mod helper { #[cfg(string)]
pub type Foo = impl Sized; #[define_opaque(Foo)]
const fn foo() -> Foo {
#[cfg(string)] String::new()
pub const FOO: Foo = String::new();
#[cfg(atomic)]
pub const FOO: Foo = std::sync::atomic::AtomicU8::new(42);
#[cfg(unit)]
pub const FOO: Foo = ();
} }
use helper::*;
#[cfg(atomic)]
#[define_opaque(Foo)]
const fn foo() -> Foo {
std::sync::atomic::AtomicU8::new(42)
}
#[cfg(unit)]
#[define_opaque(Foo)]
const fn foo() -> Foo {}
const FOO: Foo = foo();
const BAR: () = { const BAR: () = {
let _: &'static _ = &FOO; let _: &'static _ = &FOO;
//[string,atomic]~^ ERROR: destructor of `helper::Foo` cannot be evaluated at compile-time //[string,atomic,unit]~^ ERROR: destructor of `Foo` cannot be evaluated at compile-time
}; };
const BAZ: &Foo = &FOO; const BAZ: &Foo = &FOO;
@ -34,5 +38,5 @@ const BAZ: &Foo = &FOO;
fn main() { fn main() {
let _: &'static _ = &FOO; let _: &'static _ = &FOO;
//[string,atomic]~^ ERROR: temporary value dropped while borrowed //[string,atomic,unit]~^ ERROR: temporary value dropped while borrowed
} }

View file

@ -1,5 +1,5 @@
error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time error[E0493]: destructor of `Foo` cannot be evaluated at compile-time
--> $DIR/const-promoted-opaque.rs:28:26 --> $DIR/const-promoted-opaque.rs:32:26
| |
LL | let _: &'static _ = &FOO; LL | let _: &'static _ = &FOO;
| ^^^ the destructor for this type cannot be evaluated in constants | ^^^ the destructor for this type cannot be evaluated in constants
@ -8,7 +8,7 @@ LL | };
| - value is dropped here | - value is dropped here
error[E0716]: temporary value dropped while borrowed error[E0716]: temporary value dropped while borrowed
--> $DIR/const-promoted-opaque.rs:36:26 --> $DIR/const-promoted-opaque.rs:40:26
| |
LL | let _: &'static _ = &FOO; LL | let _: &'static _ = &FOO;
| ---------- ^^^ creates a temporary value which is freed while still in use | ---------- ^^^ creates a temporary value which is freed while still in use

View file

@ -0,0 +1,24 @@
error[E0493]: destructor of `Foo` cannot be evaluated at compile-time
--> $DIR/const-promoted-opaque.rs:32:26
|
LL | let _: &'static _ = &FOO;
| ^^^ the destructor for this type cannot be evaluated in constants
LL |
LL | };
| - value is dropped here
error[E0716]: temporary value dropped while borrowed
--> $DIR/const-promoted-opaque.rs:40:26
|
LL | let _: &'static _ = &FOO;
| ---------- ^^^ creates a temporary value which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL |
LL | }
| - temporary value is freed at the end of this statement
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0493, E0716.
For more information about an error, try `rustc --explain E0493`.

View file

@ -20,6 +20,7 @@ mod m {
} }
} }
#[define_opaque(NotCalledFn)]
fn mk_not_called() -> NotCalledFn { fn mk_not_called() -> NotCalledFn {
not_called::<i32> not_called::<i32>
} }

View file

@ -16,22 +16,20 @@ impl<F: Future> Task<F> {
} }
} }
mod helper { pub type F = impl Future;
use super::*; #[define_opaque(F)]
pub type F = impl Future; fn foo()
fn foo() where
where F:,
F:, {
{ async fn cb() {
async fn cb() { let a = Foo; //~ ERROR cannot find value `Foo` in this scope
let a = Foo; //~ ERROR cannot find value `Foo` in this scope
}
Task::spawn(&POOL, || cb());
} }
Task::spawn(&POOL, || cb());
} }
// Check that statics are inhabited computes they layout. // Check that statics are inhabited computes they layout.
static POOL: Task<helper::F> = Task::new(); static POOL: Task<F> = Task::new();
fn main() {} fn main() {}

Some files were not shown because too many files have changed in this diff Show more