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 = [
"itertools",
"rustc_abi",
"rustc_attr_parsing",
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",

View File

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

View File

@ -973,7 +973,14 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
_ctxt,
_ident,
_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.
visit_defaultness(vis, defaultness);
@ -987,6 +994,11 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
vis.visit_block(body);
}
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) => {
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,
_ident,
_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.
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));
visit_opt!(visitor, visit_contract, contract);
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) => {
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),
*span,
*id
))
));
}
ExprKind::Block(block, 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::*;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::PredicateOrigin;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, PredicateOrigin};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@ -209,6 +208,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics,
body,
contract,
define_opaque,
..
}) => {
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),
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() }
})
}
@ -779,7 +780,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
(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
// any impl method or callees.
let names = self.lower_fn_params_to_names(&sig.decl);
@ -791,9 +792,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind,
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)
}
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(
sig.span,
i.span,
@ -812,6 +826,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind,
attrs,
);
self.lower_define_opaque(hir_id, &define_opaque);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
}
AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
@ -911,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
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(
sig.span,
i.span,
@ -930,6 +945,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind,
attrs,
);
self.lower_define_opaque(hir_id, &define_opaque);
(generics, hir::ImplItemKind::Fn(sig, body_id))
}
@ -1657,6 +1673,35 @@ impl<'hir> LoweringContext<'_, 'hir> {
(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(
&mut self,
ident: Ident,

View File

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

View File

@ -917,7 +917,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(self, visit_attribute, &item.attrs);
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);
let is_intrinsic =

View File

@ -24,7 +24,6 @@ use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::IdentPrinter;
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::{self, Breaks};
@ -1978,15 +1977,7 @@ impl<'a> State<'a> {
) {
self.ibox(INDENT_UNIT);
self.print_formal_generic_params(generic_params);
let generics = ast::Generics {
params: ThinVec::new(),
where_clause: ast::WhereClause {
has_where_token: false,
predicates: ThinVec::new(),
span: DUMMY_SP,
},
span: DUMMY_SP,
};
let generics = ast::Generics::default();
let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
self.print_fn(decl, header, name, &generics);
self.end();

View File

@ -650,7 +650,16 @@ impl<'a> State<'a> {
attrs: &[ast::Attribute],
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() {
self.head("");
}
@ -698,7 +707,7 @@ impl<'a> State<'a> {
}
self.print_generic_params(&generics.params);
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) {

View File

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

View File

@ -88,6 +88,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
generics: Generics::default(),
contract: None,
body,
define_opaque: None,
}));
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(),
contract: None,
body: Some(d_body),
define_opaque: None,
});
let mut rustc_ad_attr =
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,
contract: None,
body: Some(body_block),
define_opaque: None,
})),
tokens: None,
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@ This means
type Foo<T> = impl std::fmt::Debug;
#[define_opaque(Foo)]
fn foo() -> Foo<u32> {
5u32
}
@ -19,6 +20,7 @@ is not accepted. If it were accepted, one could create unsound situations like
type Foo<T> = impl Default;
#[define_opaque(Foo)]
fn foo() -> Foo<u32> {
5u32
}
@ -36,6 +38,7 @@ Instead you need to make the function generic:
type Foo<T> = impl std::fmt::Debug;
#[define_opaque(Foo)]
fn foo<U>() -> Foo<U> {
5u32
}
@ -56,6 +59,7 @@ use std::fmt::Debug;
type Foo<T: Debug> = impl Debug;
#[define_opaque(Foo)]
fn foo<U: Debug>() -> Foo<U> {
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.
#[instrument(level = "trace", skip(resources))]
#[cfg_attr(not(bootstrap), define_opaque(LazyFallbackBundle))]
pub fn fallback_fluent_bundle(
resources: Vec<&'static str>,
with_directionality_markers: bool,

View File

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

View File

@ -1307,13 +1307,18 @@ impl Attribute {
#[derive(Debug)]
pub struct AttributeMap<'tcx> {
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.
pub opt_hash: Option<Fingerprint>,
}
impl<'tcx> AttributeMap<'tcx> {
pub const EMPTY: &'static AttributeMap<'static> =
&AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) };
pub const EMPTY: &'static AttributeMap<'static> = &AttributeMap {
map: SortedMap::new(),
opt_hash: Some(Fingerprint::ZERO),
define_opaque: None,
};
#[inline]
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) {
// 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.
let AttributeMap { opt_hash, map: _ } = *self;
let AttributeMap { opt_hash, define_opaque: _, map: _ } = *self;
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_tait_forward_compat = item constrains opaque type that is not in its signature
.note = this item must mention the opaque type in its signature in order to be able to register hidden types
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_tait_forward_compat2 = item does not constrain `{$opaque_type}`
.note = consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
.opaque = this opaque type is supposed to be constrained
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(());
}
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) =
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
}
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
let scope = tcx.hir_get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
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()
tcx.hir_walk_toplevel_module(&mut locator).break_value()
}
}
}

View File

@ -1,14 +1,13 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::DUMMY_SP;
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.
/// 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")]
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![] };
debug!(?scope);
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),
}
}
tcx.hir_walk_toplevel_module(&mut locator);
if let Some(hidden) = locator.found {
// 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 {
span: tcx.def_span(def_id),
name: tcx.item_ident(parent_def_id.to_def_id()),
what: match tcx.hir_node(scope) {
_ 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",
},
what: "crate",
});
Ty::new_error(tcx, reported)
}
@ -176,6 +141,13 @@ impl TaitConstraintLocator<'_> {
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
// "non-defining use" errors for them.
// Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former
@ -215,8 +187,6 @@ impl TaitConstraintLocator<'_> {
return;
}
let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
let mut constrained = false;
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
if opaque_type_key.def_id != self.def_id {
@ -224,20 +194,6 @@ impl TaitConstraintLocator<'_> {
}
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 =
self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
opaque_type_key,
@ -309,19 +265,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
}
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
if it.owner_id.def_id != self.def_id {
self.check(it.owner_id.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>) {
trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
if it.owner_id.def_id != self.def_id {
self.check(it.owner_id.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>) {
trace!(?it.owner_id);

View File

@ -424,16 +424,6 @@ pub(crate) struct UnconstrainedOpaqueType {
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)]
#[diag(hir_analysis_tait_forward_compat2)]
#[note]

View File

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

View File

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

View File

@ -24,6 +24,7 @@ pub trait EraseType: Copy {
pub type Erase<T: EraseType> = Erased<impl Copy>;
#[inline(always)]
#[cfg_attr(not(bootstrap), define_opaque(Erase))]
pub fn erase<T: EraseType>(src: T) -> Erase<T> {
// Ensure the sizes match
const {
@ -47,6 +48,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
/// Restores an erased value.
#[inline(always)]
#[cfg_attr(not(bootstrap), define_opaque(Erase))]
pub fn restore<T: EraseType>(value: Erase<T>) -> T {
let value: Erased<<T as EraseType>::Result> = value;
// 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)?;
(
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)) {
if self.eat_keyword(exp!(Crate)) {

View File

@ -397,32 +397,37 @@ pub(crate) enum AliasPossibility {
#[derive(Copy, Clone, Debug)]
pub(crate) enum PathSource<'a> {
// Type paths `Path`.
/// Type paths `Path`.
Type,
// Trait paths in bounds or impls.
/// Trait paths in bounds or impls.
Trait(AliasPossibility),
// Expression paths `path`, with optional parent context.
/// Expression paths `path`, with optional parent context.
Expr(Option<&'a Expr>),
// Paths in path patterns `Path`.
/// Paths in path patterns `Path`.
Pat,
// Paths in struct expressions and patterns `Path { .. }`.
/// Paths in struct expressions and patterns `Path { .. }`.
Struct,
// Paths in tuple struct patterns `Path(..)`.
/// Paths in tuple struct patterns `Path(..)`.
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),
// Paths in delegation item
/// Paths in delegation item
Delegation,
/// An arg in a `use<'a, N>` precise-capturing bound.
PreciseCapturingArg(Namespace),
// Paths that end with `(..)`, for return type notation.
/// Paths that end with `(..)`, for return type notation.
ReturnTypeNotation,
/// Paths from `#[define_opaque]` attributes
DefineOpaques,
}
impl<'a> PathSource<'a> {
fn namespace(self) -> Namespace {
match self {
PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
PathSource::Type
| PathSource::Trait(_)
| PathSource::Struct
| PathSource::DefineOpaques => TypeNS,
PathSource::Expr(..)
| PathSource::Pat
| PathSource::TupleStruct(..)
@ -443,6 +448,7 @@ impl<'a> PathSource<'a> {
| PathSource::ReturnTypeNotation => true,
PathSource::Trait(_)
| PathSource::TraitItem(..)
| PathSource::DefineOpaques
| PathSource::Delegation
| PathSource::PreciseCapturingArg(..) => false,
}
@ -450,6 +456,7 @@ impl<'a> PathSource<'a> {
fn descr_expected(self) -> &'static str {
match &self {
PathSource::DefineOpaques => "type alias or associated type with opaqaue types",
PathSource::Type => "type",
PathSource::Trait(_) => "trait",
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 {
match self {
PathSource::DefineOpaques => {
matches!(
res,
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::TyAlias
| DefKind::AssocTy,
_
) | Res::SelfTyAlias { .. }
)
}
PathSource::Type => matches!(
res,
Res::Def(
@ -572,16 +592,16 @@ impl<'a> PathSource<'a> {
match (self, has_unexpected_resolution) {
(PathSource::Trait(_), true) => E0404,
(PathSource::Trait(_), false) => E0405,
(PathSource::Type, true) => E0573,
(PathSource::Type, false) => E0412,
(PathSource::Type | PathSource::DefineOpaques, true) => E0573,
(PathSource::Type | PathSource::DefineOpaques, false) => E0412,
(PathSource::Struct, true) => E0574,
(PathSource::Struct, false) => E0422,
(PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
(PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
(PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
(PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
(PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
(PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
(PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, true) => E0575,
(PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, false) => E0576,
(PathSource::PreciseCapturingArg(..), true) => E0799,
(PathSource::PreciseCapturingArg(..), false) => E0800,
}
@ -2006,6 +2026,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
| PathSource::Pat
| PathSource::Struct
| PathSource::TupleStruct(..)
| PathSource::DefineOpaques
| PathSource::Delegation => true,
};
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(
&generics.params,
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),
);
for (id, path) in define_opaque.iter().flatten() {
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
}
}
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);
for (id, path) in define_opaque.iter().flatten() {
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
}
}
AssocItemKind::Delegation(delegation) => {
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");
// We also need a new scope for the impl item type parameters.
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)
},
);
for (id, path) in define_opaque.iter().flatten() {
self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
}
}
AssocItemKind::Type(box TyAlias { generics, .. }) => {
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_type_parameter_fallback,
default_type_params,
define_opaque,
delayed_bug_from_inside_query,
deny,
deprecated,

View File

@ -395,11 +395,28 @@ impl<T> Trait<T> for X {
let sp = tcx
.def_ident_span(body_owner_def_id)
.unwrap_or_else(|| tcx.def_span(body_owner_def_id));
diag.span_note(
sp,
"this item must have the opaque type in its signature in order to \
be able to register hidden types",
);
let mut alias_def_id = opaque_ty.def_id;
while let DefKind::OpaqueTy = tcx.def_kind(alias_def_id) {
alias_def_id = tcx.parent(alias_def_id);
}
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
// suggestion.

View File

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

View File

@ -1,8 +1,8 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{CRATE_HIR_ID, intravisit};
use rustc_middle::bug;
use rustc_middle::query::Providers;
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
/// associated types of the same impl block.
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> {
fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
let mode = match tcx.def_kind(tcx.local_parent(item)) {
DefKind::Impl { of_trait: true } => CollectionMode::ImplTraitInAssocTypes,
_ => CollectionMode::TypeAliasImplTraitTransition,
let mode = match tcx.def_kind(item) {
DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => {
CollectionMode::ImplTraitInAssocTypes
}
DefKind::TyAlias => CollectionMode::Taits,
_ => CollectionMode::RpitAndAsyncFnOnly,
};
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))]
fn collect_taits_declared_in_body(&mut self) {
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.
let origin = self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local());
trace!(?origin);
match origin {
match self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local()) {
rustc_hir::OpaqueTyOrigin::FnReturn { .. }
| rustc_hir::OpaqueTyOrigin::AsyncFn { .. } => {}
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
if !in_assoc_ty && !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
return;
rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => match self.mode {
// If we are collecting opaques in an assoc method, we are only looking at assoc types
// 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());
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> {
@ -210,6 +222,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
self.visit_opaque_ty(alias_ty);
}
// 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() => {
self.tcx
.type_of(alias_ty.def_id)
@ -283,28 +296,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
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()),
}
}
@ -317,7 +308,9 @@ fn opaque_types_defined_by<'tcx>(
let kind = tcx.def_kind(item);
trace!(?kind);
let mut collector = OpaqueTypeCollector::new(tcx, item);
collector.collect_taits_from_defines_attr();
super::sig_types::walk_types(tcx, item, &mut collector);
match kind {
DefKind::AssocFn
| DefKind::Fn
@ -350,8 +343,7 @@ fn opaque_types_defined_by<'tcx>(
| DefKind::GlobalAsm
| DefKind::Impl { .. }
| DefKind::SyntheticCoroutineBody => {}
// Closures and coroutines are type checked with their parent, so we need to allow all
// opaques from the closure signature *and* from the parent body.
// Closures and coroutines are type checked with their parent
DefKind::Closure | DefKind::InlineConst => {
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 */
}
/// 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.
#[allow_internal_unstable(builtin_syntax)]
#[unstable(

View File

@ -111,3 +111,11 @@ pub use crate::macros::builtin::type_ascribe;
reason = "placeholder syntax for deref patterns"
)]
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::*;
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 {
move || {
// 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;
// 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
// rather than glob imported because we want docs to show these re-exports as
// 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>) {
match item.kind {
ItemKind::Static(_, _, _)
ItemKind::Static(..)
| ItemKind::Const(_, _, _)
| ItemKind::Fn { .. }
| ItemKind::Macro(_, _)

View File

@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
generics: lg,
contract: lc,
body: lb,
define_opaque: _,
}),
Fn(box ast::Fn {
defaultness: rd,
@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
generics: rg,
contract: rc,
body: rb,
define_opaque: _,
}),
) => {
eq_defaultness(*ld, *rd)
@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
generics: lg,
contract: lc,
body: lb,
define_opaque: _,
}),
Fn(box ast::Fn {
defaultness: rd,
@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
generics: rg,
contract: rc,
body: rb,
define_opaque: _,
}),
) => {
eq_defaultness(*ld, *rd)
@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
generics: lg,
contract: lc,
body: lb,
define_opaque: _,
}),
Fn(box ast::Fn {
defaultness: rd,
@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
generics: rg,
contract: rc,
body: rb,
define_opaque: _,
}),
) => {
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;
//~^ implied_bounds_in_impls
#[define_opaque(Tait)]
fn define() -> Tait {
&mut [] as &mut [()]
}

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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 {
| ^

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-104817.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-53092-2.rs
ui/type-alias-impl-trait/issue-53092.rs

View File

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

View File

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

View File

@ -9,47 +9,41 @@
extern crate core;
mod defining_module {
pub type Type1 = impl Send;
pub type Type2 = impl Send;
pub type Type3 = impl Send;
pub type Type4 = impl Send;
pub type Type1 = impl Send;
pub type Type2 = impl Send;
pub type Type3 = impl Send;
pub type Type4 = impl Send;
pub fn foo()
where
Type1: 'static,
Type2: 'static,
Type4: 'static,
{
// 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;
#[define_opaque(Type1, Type2, Type4)]
pub fn foo() {
// 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;
#[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
@ -78,15 +72,15 @@ pub fn foo11(_: &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: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"}
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"}
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}

View File

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

View File

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

View File

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

View File

@ -1,16 +1,26 @@
//@ known-bug: rust-lang/rust#125185
//@ compile-flags: -Zvalidate-mir
#![feature(type_alias_impl_trait)]
type Foo = impl Send;
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 {
0 | 0 => {}
_ => (),
}
}
fn main() {}

View File

@ -8,14 +8,18 @@ use std::path::Path;
struct A {
pub func: fn(check: Bar, b: Option<&Path>),
}
const MY_A: A = A {
func: |check, b| {
if check {
()
} else if let Some(_) = b.and_then(|p| p.parent()) {
()
}
},
};
#[define_opaque(Bar)]
fn foo() -> A {
A {
func: |check, b| {
if check {
()
} else if let Some(_) = b.and_then(|p| p.parent()) {
()
}
},
}
}
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
//@ compile-flags: -Zvalidate-mir --crate-type=lib
//@ compile-flags: -Zvalidate-mir
#![feature(type_alias_impl_trait)]
type Tait = impl Sized;
@ -7,6 +7,9 @@ type Tait = impl Sized;
trait Foo<'a>: Bar<'a, 'a, Tait> {}
trait Bar<'a, 'b, T> {}
#[define_opaque(Tait)]
fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
let _ = x as &dyn Bar<'_, '_, ()>;
}
fn main() {}

View File

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

View File

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

View File

@ -11,7 +11,8 @@ impl Foo<i32> {
type Tait = impl Sized;
fn bar(_: Tait) {
#[define_opaque(Tait)]
fn bar() {
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;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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

View File

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

View File

@ -179,19 +179,25 @@ where
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 unconstrained opaque type
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 unconstrained opaque type
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 unconstrained opaque type
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 unconstrained opaque type
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 unconstrained opaque type
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 unconstrained opaque type
trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
//~^ 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
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;
| ---------- ^^^^^^^^^^ re-bound here
@ -333,7 +333,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
| `Item` bound here first
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;
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -341,7 +341,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
| `Item` bound here first
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>;
| ---------- ^^^^^^^^^^ re-bound here
@ -349,7 +349,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
| `Item` bound here first
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>;
| ---------- ^^^^^^^^^^ 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`
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>;
| ---------- ^^^^^^^^^^ re-bound here
@ -367,7 +367,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first
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>;
| ---------- ^^^^^^^^^^ 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`
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>;
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -385,7 +385,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
| `Item` bound here first
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>;
| ------------- ^^^^^^^^^^^^^ 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`
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>> {}
| ---------- ^^^^^^^^^^ re-bound here
@ -403,7 +403,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
| `Item` bound here first
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>> {}
| ---------- ^^^^^^^^^^ re-bound here
@ -411,7 +411,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
| `Item` bound here first
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>> {}
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -419,7 +419,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
| `Item` bound here first
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> {}
| ---------- ^^^^^^^^^^ re-bound here
@ -427,7 +427,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
| `Item` bound here first
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> {}
| ---------- ^^^^^^^^^^ 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`
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> {}
| ---------- ^^^^^^^^^^ 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`
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> {}
| ---------- ^^^^^^^^^^ re-bound here
@ -455,7 +455,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
| `Item` bound here first
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> {}
| ---------- ^^^^^^^^^^ 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`
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> {}
| ---------- ^^^^^^^^^^ 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`
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> {}
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -483,7 +483,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
| `Item` bound here first
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> {}
| ------------- ^^^^^^^^^^^^^ 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`
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> {}
| ------------- ^^^^^^^^^^^^^ 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`
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>,
| ---------- ^^^^^^^^^^ re-bound here
@ -511,7 +511,7 @@ LL | T: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first
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>,
| ---------- ^^^^^^^^^^ re-bound here
@ -519,7 +519,7 @@ LL | T: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first
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>,
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -527,7 +527,7 @@ LL | T: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first
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>,
| ---------- ^^^^^^^^^^ re-bound here
@ -535,7 +535,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
| `Item` bound here first
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>,
| ---------- ^^^^^^^^^^ re-bound here
@ -545,7 +545,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
= 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
--> $DIR/duplicate.rs:234:32
--> $DIR/duplicate.rs:240:32
|
LL | Self: Iterator<Item: Copy, Item: Send>,
| ---------- ^^^^^^^^^^ re-bound here
@ -555,7 +555,7 @@ LL | Self: Iterator<Item: Copy, Item: Send>,
= 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
--> $DIR/duplicate.rs:242:32
--> $DIR/duplicate.rs:248:32
|
LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here
@ -563,7 +563,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
| `Item` bound here first
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>,
| ---------- ^^^^^^^^^^ re-bound here
@ -573,7 +573,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
= 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
--> $DIR/duplicate.rs:242:32
--> $DIR/duplicate.rs:248:32
|
LL | Self: Iterator<Item: Copy, Item: Copy>,
| ---------- ^^^^^^^^^^ re-bound here
@ -583,7 +583,7 @@ LL | Self: Iterator<Item: Copy, Item: Copy>,
= 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
--> $DIR/duplicate.rs:250:35
--> $DIR/duplicate.rs:256:35
|
LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -591,7 +591,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
| `Item` bound here first
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>,
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -601,7 +601,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
= 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
--> $DIR/duplicate.rs:250:35
--> $DIR/duplicate.rs:256:35
|
LL | Self: Iterator<Item: 'static, Item: 'static>,
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -611,7 +611,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>,
= 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
--> $DIR/duplicate.rs:257:34
--> $DIR/duplicate.rs:263:34
|
LL | type A: Iterator<Item: Copy, Item: Send>;
| ---------- ^^^^^^^^^^ re-bound here
@ -619,7 +619,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>;
| `Item` bound here first
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>;
| ---------- ^^^^^^^^^^ 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`
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>;
| ---------- ^^^^^^^^^^ re-bound here
@ -637,7 +637,7 @@ LL | type A: Iterator<Item: Copy, Item: Copy>;
| `Item` bound here first
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>;
| ---------- ^^^^^^^^^^ 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`
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>;
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -655,7 +655,7 @@ LL | type A: Iterator<Item: 'static, Item: 'static>;
| `Item` bound here first
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>;
| ------------- ^^^^^^^^^^^^^ re-bound here
@ -697,7 +697,55 @@ help: consider specifying the generic argument
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.
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>;
#[define_opaque(Et1)]
fn def_et1() -> Et1 {
S1
}
@ -39,6 +40,7 @@ pub fn use_et1() {
}
type Et2 = impl Tr1<As1: 'static>;
#[define_opaque(Et2)]
fn def_et2() -> Et2 {
S1
}
@ -47,6 +49,7 @@ pub fn use_et2() {
}
type Et3 = impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>;
#[define_opaque(Et3)]
fn def_et3() -> Et3 {
struct A;
impl Tr1 for A {
@ -68,6 +71,7 @@ pub fn use_et3() {
}
type Et4 = impl Tr1<As1: for<'a> Tr2<'a>>;
#[define_opaque(Et4)]
fn def_et4() -> Et4 {
#[derive(Copy, Clone)]
struct A;

View File

@ -4,11 +4,14 @@
#![feature(type_alias_impl_trait)]
type Tait = impl AsyncFn();
#[define_opaque(Tait)]
fn tait() -> Tait {
|| async {}
}
fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x }
fn foo(x: impl AsyncFn()) -> impl AsyncFn() {
x
}
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
// in the type.
#[define_opaque(Func)]
fn null_function_ptr() -> Func {
None::<for<'a> fn(&'a ())>
}
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.
#[define_opaque(ServeFut)]
fn serve() -> ServeFut {
async move {
let x = 5;

View File

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

View File

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

View File

@ -176,7 +176,7 @@ LL | type AFoobar = impl Foobar;
| --------------------------- not a macro definition
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -200,7 +200,7 @@ LL | type Bar;
| --------- not a macro definition
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -209,7 +209,7 @@ LL | const FOO: u32 = 3;
| ------------------- not a macro definition
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)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

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

View File

@ -1,5 +1,5 @@
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
| - ^ 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)`
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;
| -- 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.
#![feature(type_alias_impl_trait)]
type OpaqueClosure = impl Sized;
#[define_opaque(OpaqueClosure)]
fn defining_use() -> OpaqueClosure {
|| ()
}

View File

@ -1,5 +1,5 @@
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> {}
| ------------------------------------- first implementation here

View File

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

View File

@ -1,5 +1,5 @@
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> {}
| --------------------------------------- first implementation here

View File

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

View File

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

View File

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

View File

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

View File

@ -4,14 +4,13 @@
// A regression test for #105787
#![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> {
//[next]~^ ERROR type annotations needed
x
}
pub type Alias<T> = impl Sized;
#[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> {
@ -25,12 +24,12 @@ trait Trait<T> {
impl<T> Trait<T> for T {
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
type Assoc = usize;
}
fn main() {
let x: Box<u32> = defining_scope::cast::<()>(Container { x: 0 }).x;
let x: Box<u32> = cast::<()>(Container { x: 0 }).x;
println!("{}", *x);
}

View File

@ -7,6 +7,7 @@
type Identity<T> = impl Sized;
#[define_opaque(Identity)]
fn define_identity<T>(x: T) -> Identity<T> {
x
}
@ -16,6 +17,7 @@ impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
type Opaque<T> = impl Sized;
#[define_opaque(Opaque)]
fn define_local<T>() -> Opaque<T> {
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`)
--> $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> {}
| ^ 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
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> {}
| ^ 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;
fn with_bound<const N: usize>() -> Foo
#[define_opaque(Foo)]
fn with_bound<const N: usize>()
where
[u8; (N / 2) as usize]: Sized,
{
let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
//~^ ERROR mismatched types
//~| ERROR non-primitive cast: `usize` as `Foo`
todo!()
}
fn main() {

View File

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/opaque_type.rs:10:17
--> $DIR/opaque_type.rs:11:17
|
LL | type Foo = impl Sized;
| ---------- the found opaque type
@ -11,7 +11,7 @@ LL | let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
found opaque type `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];
| ^^^^^^^^^^^^^^ 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)]
type Foo = impl Sized;
//~^ ERROR: cycle
//~| ERROR: cycle
#[define_opaque(Foo)]
fn foo<const C: Foo>() {}
//~^ ERROR: `Foo` is forbidden as the type of a const generic parameter
//~| ERROR: item does not constrain

View File

@ -1,26 +1,26 @@
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>() {}
| ^^^
|
= note: the only supported types are integers, `bool`, and `char`
error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
--> $DIR/opaque_types.rs:7:4
error: item does not constrain `Foo::{opaque#0}`
--> $DIR/opaque_types.rs:6:4
|
LL | fn foo<const C: Foo>() {}
| ^^^
|
= note: consider moving the opaque type's declaration and defining uses into a separate module
note: this opaque type is in the signature
= note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
note: this opaque type is supposed to be constrained
--> $DIR/opaque_types.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/opaque_types.rs:12:11
--> $DIR/opaque_types.rs:11:11
|
LL | type Foo = impl Sized;
| ---------- the expected opaque type
@ -31,106 +31,6 @@ LL | foo::<42>();
= note: expected opaque type `Foo`
found type `{integer}`
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
--> $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: aborting due to 3 previous errors
error[E0391]: cycle detected when 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 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`.
For more information about this error, try `rustc --explain E0308`.

View File

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

View File

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

View File

@ -3,14 +3,20 @@ type Foo = impl Send;
struct A;
const VALUE: Foo = value();
//~^ ERROR cannot find function `value` in this scope
#[define_opaque(Foo)]
//~^ ERROR unstable library feature
const fn foo() -> Foo {
value()
//~^ ERROR cannot find function `value` in this scope
}
const VALUE: Foo = foo();
fn test() {
match VALUE {
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
--> $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
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();
| ^^^^^ not found in this scope
LL | value()
| ^^^^^ help: a constant with a similar name exists: `VALUE`
...
LL | const VALUE: Foo = foo();
| ------------------------- similarly named constant `VALUE` defined here
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;
| --------- the expected opaque type
@ -27,14 +40,14 @@ LL | 0 | 0 => {}
|
= note: expected opaque type `Foo`
found type `{integer}`
note: this item must have the opaque type in its signature in order to be able to register hidden types
--> $DIR/ice-unhandled-type-122191.rs:9:4
note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
--> $DIR/ice-unhandled-type-122191.rs:15:4
|
LL | fn test() {
| ^^^^
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;
| --------- the expected opaque type
@ -46,13 +59,13 @@ LL | 0 | 0 => {}
|
= note: expected opaque type `Foo`
found type `{integer}`
note: this item must have the opaque type in its signature in order to be able to register hidden types
--> $DIR/ice-unhandled-type-122191.rs:9:4
note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
--> $DIR/ice-unhandled-type-122191.rs:15:4
|
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.
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
--> $DIR/const-promoted-opaque.rs:28:26
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
@ -8,13 +8,13 @@ LL | };
| - value is dropped here
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;
| ^^^^ this borrow of an interior mutable value may end up in the final value
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;
| ---------- ^^^ 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
//! result of our analysis to compute the result of our analysis.
//@[unit] check-pass
pub type Foo = impl Sized;
mod helper {
pub type Foo = impl Sized;
#[cfg(string)]
pub const FOO: Foo = String::new();
#[cfg(atomic)]
pub const FOO: Foo = std::sync::atomic::AtomicU8::new(42);
#[cfg(unit)]
pub const FOO: Foo = ();
#[cfg(string)]
#[define_opaque(Foo)]
const fn foo() -> Foo {
String::new()
}
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: () = {
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;
@ -34,5 +38,5 @@ const BAZ: &Foo = &FOO;
fn main() {
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
--> $DIR/const-promoted-opaque.rs:28:26
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
@ -8,7 +8,7 @@ LL | };
| - value is dropped here
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;
| ---------- ^^^ 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 {
not_called::<i32>
}

View File

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

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