Implement #[define_opaque] attribute for functions.

This commit is contained in:
Oli Scherer 2024-07-26 10:04:02 +00:00 committed by Oli Scherer
parent 2c6a12ec44
commit cb4751d4b8
653 changed files with 2911 additions and 2580 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,31 @@ 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()
// TODO: error reporting for non-local items being mentioned and tests that go through these code paths
.map(|(id, _path)| {
self.resolver
.get_partial_res(*id)
.unwrap()
.expect_full_res()
.def_id()
.expect_local()
});
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)]
@ -97,6 +98,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 [LocalDefId]>,
/// Attributes inside the owner being lowered.
attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
/// Collect items that were created by lowering the current owner.
@ -154,6 +157,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// HirId handling.
bodies: Vec::new(),
define_opaque: None,
attrs: SortedMap::default(),
children: Vec::default(),
contract_ensures: None,
@ -546,6 +550,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);
@ -579,6 +584,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)]
@ -598,6 +604,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)]
@ -617,7 +624,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

@ -38,6 +38,7 @@ mod compile_error;
mod concat;
mod concat_bytes;
mod concat_idents;
mod define_opaque;
mod derive;
mod deriving;
mod edition_panic;
@ -113,6 +114,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(super) 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

@ -208,6 +208,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

@ -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 [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,29 @@ 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 &define in defines {
trace!(?define);
let mode = std::mem::replace(&mut self.mode, CollectionMode::Taits);
// TODO: check that opaque types were introduced and error otherwise (also add tests)
super::sig_types::walk_types(self.tcx, define, self);
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 +219,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 +293,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 +305,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 +340,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() {}

View File

@ -1,8 +1,8 @@
error[E0425]: cannot find value `Foo` in this scope
--> $DIR/layout-error.rs:27:21
--> $DIR/layout-error.rs:26:17
|
LL | let a = Foo;
| ^^^ not found in this scope
LL | let a = Foo;
| ^^^ not found in this scope
error: aborting due to 1 previous error

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