mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 12:36:47 +00:00
Implement #[define_opaque]
attribute for functions.
This commit is contained in:
parent
2c6a12ec44
commit
cb4751d4b8
@ -4529,6 +4529,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"rustc_abi",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 })
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
/// }
|
||||
|
@ -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)];
|
||||
|
@ -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)));
|
||||
|
54
compiler/rustc_builtin_macros/src/define_opaque.rs
Normal file
54
compiler/rustc_builtin_macros/src/define_opaque.rs
Normal 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]
|
||||
}
|
@ -1040,6 +1040,7 @@ impl<'a> MethodDef<'a> {
|
||||
generics: fn_generics,
|
||||
contract: None,
|
||||
body: Some(body_block),
|
||||
define_opaque: None,
|
||||
})),
|
||||
tokens: None,
|
||||
})
|
||||
|
@ -83,6 +83,7 @@ impl AllocFnFactory<'_, '_> {
|
||||
generics: Generics::default(),
|
||||
contract: None,
|
||||
body,
|
||||
define_opaque: None,
|
||||
}));
|
||||
let item = self.cx.item(
|
||||
self.span,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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![],
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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] {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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]`
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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]
|
||||
|
@ -43,6 +43,7 @@ declare_lint! {
|
||||
///
|
||||
/// type Tait = impl Sized;
|
||||
///
|
||||
/// #[define_opaque(Tait)]
|
||||
/// fn test() -> impl Trait<Assoc = Tait> {
|
||||
/// 42
|
||||
/// }
|
||||
|
@ -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 {
|
||||
|
@ -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`.
|
||||
|
@ -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)) {
|
||||
|
@ -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());
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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" }
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
@ -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(_, _)
|
||||
|
@ -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)
|
||||
|
@ -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() {}
|
@ -192,6 +192,7 @@ impl Atpit for () {
|
||||
|
||||
type Tait = impl DerefMut;
|
||||
//~^ implied_bounds_in_impls
|
||||
#[define_opaque(Tait)]
|
||||
fn define() -> Tait {
|
||||
&mut [] as &mut [()]
|
||||
}
|
||||
|
@ -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 [()]
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ mod issue10041 {
|
||||
struct Bomb2;
|
||||
|
||||
impl Bomb2 {
|
||||
#[define_opaque(X)]
|
||||
pub fn new() -> X {
|
||||
//~^ ERROR: overflow evaluating the requirement
|
||||
0i32
|
||||
|
@ -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 {
|
||||
| ^
|
||||
|
@ -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
|
||||
|
@ -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"}
|
||||
|
@ -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) {}
|
||||
|
@ -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"}
|
||||
|
@ -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 {}
|
||||
|
@ -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| ());
|
||||
}
|
||||
|
@ -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| ());
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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() {}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
@ -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() {}
|
||||
|
@ -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 {
|
||||
()
|
||||
}
|
||||
|
@ -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>
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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| {};
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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`.
|
||||
|
@ -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;
|
||||
|
@ -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()>() {}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -13,6 +13,7 @@ pub trait Trait {}
|
||||
|
||||
pub type TAIT<T> = impl Trait;
|
||||
|
||||
#[define_opaque(TAIT)]
|
||||
async fn foo<T>() -> TAIT<T> {
|
||||
Foo
|
||||
}
|
||||
|
@ -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) {}
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|| ()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -7,6 +7,7 @@
|
||||
//@ [specialized]check-pass
|
||||
|
||||
type OpaqueCoroutine = impl Sized;
|
||||
#[define_opaque(OpaqueCoroutine)]
|
||||
fn defining_use() -> OpaqueCoroutine {
|
||||
#[coroutine]
|
||||
|| {
|
||||
|
@ -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
|
||||
|
@ -8,6 +8,7 @@ struct Outer<T: ?Sized> {
|
||||
|
||||
type InnerSend<T: ?Sized> = impl Send;
|
||||
|
||||
#[define_opaque(InnerSend)]
|
||||
fn constrain<T: ?Sized>() -> InnerSend<T> {
|
||||
()
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ struct Send<T> {
|
||||
|
||||
type InnerSend<T> = impl Sized;
|
||||
|
||||
#[define_opaque(InnerSend)]
|
||||
fn constrain<T>() -> InnerSend<T> {
|
||||
()
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`)
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
24
tests/ui/consts/const-promoted-opaque.unit.stderr
Normal file
24
tests/ui/consts/const-promoted-opaque.unit.stderr
Normal 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`.
|
@ -20,6 +20,7 @@ mod m {
|
||||
}
|
||||
}
|
||||
|
||||
#[define_opaque(NotCalledFn)]
|
||||
fn mk_not_called() -> NotCalledFn {
|
||||
not_called::<i32>
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user