mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
Auto merge of #128440 - oli-obk:defines, r=lcnr
Add `#[define_opaques]` attribute and require it for all type-alias-impl-trait sites that register a hidden type Instead of relying on the signature of items to decide whether they are constraining an opaque type, the opaque types that the item constrains must be explicitly listed. A previous version of this PR used an actual attribute, but had to keep the resolved `DefId`s in a side table. Now we just lower to fields in the AST that have no surface syntax, instead a builtin attribute macro fills in those fields where applicable. Note that for convenience referencing opaque types in associated types from associated methods on the same impl will not require an attribute. If that causes problems `#[defines()]` can be used to overwrite the default of searching for opaques in the signature. One wart of this design is that closures and static items do not have generics. So since I stored the opaques in the generics of functions, consts and methods, I would need to add a custom field to closures and statics to track this information. During a T-types discussion we decided to just not do this for now. fixes #131298
This commit is contained in:
commit
6650252439
@ -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,35 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
(lowered_generics, res)
|
||||
}
|
||||
|
||||
pub(super) fn lower_define_opaque(
|
||||
&mut self,
|
||||
hir_id: HirId,
|
||||
define_opaque: &Option<ThinVec<(NodeId, Path)>>,
|
||||
) {
|
||||
assert_eq!(self.define_opaque, None);
|
||||
assert!(hir_id.is_owner());
|
||||
let Some(define_opaque) = define_opaque.as_ref() else {
|
||||
return;
|
||||
};
|
||||
let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
|
||||
let res = self.resolver.get_partial_res(*id).unwrap();
|
||||
let Some(did) = res.expect_full_res().opt_def_id() else {
|
||||
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
|
||||
return None;
|
||||
};
|
||||
let Some(did) = did.as_local() else {
|
||||
self.dcx().span_err(
|
||||
path.span,
|
||||
"only opaque types defined in the local crate can be defined",
|
||||
);
|
||||
return None;
|
||||
};
|
||||
Some((self.lower_span(path.span), did))
|
||||
});
|
||||
let define_opaque = self.arena.alloc_from_iter(define_opaque);
|
||||
self.define_opaque = Some(define_opaque);
|
||||
}
|
||||
|
||||
pub(super) fn lower_generic_bound_predicate(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
|
@ -35,6 +35,7 @@
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(rustdoc_internals)]
|
||||
@ -98,6 +99,8 @@ struct LoweringContext<'a, 'hir> {
|
||||
|
||||
/// Bodies inside the owner being lowered.
|
||||
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
|
||||
/// `#[define_opaque]` attributes
|
||||
define_opaque: Option<&'hir [(Span, LocalDefId)]>,
|
||||
/// Attributes inside the owner being lowered.
|
||||
attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
|
||||
/// Collect items that were created by lowering the current owner.
|
||||
@ -155,6 +158,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
// HirId handling.
|
||||
bodies: Vec::new(),
|
||||
define_opaque: None,
|
||||
attrs: SortedMap::default(),
|
||||
children: Vec::default(),
|
||||
contract_ensures: None,
|
||||
@ -547,6 +551,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
let current_attrs = std::mem::take(&mut self.attrs);
|
||||
let current_bodies = std::mem::take(&mut self.bodies);
|
||||
let current_define_opaque = std::mem::take(&mut self.define_opaque);
|
||||
let current_ident_and_label_to_local_id =
|
||||
std::mem::take(&mut self.ident_and_label_to_local_id);
|
||||
|
||||
@ -580,6 +585,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
self.attrs = current_attrs;
|
||||
self.bodies = current_bodies;
|
||||
self.define_opaque = current_define_opaque;
|
||||
self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@ -599,6 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
|
||||
let attrs = std::mem::take(&mut self.attrs);
|
||||
let mut bodies = std::mem::take(&mut self.bodies);
|
||||
let define_opaque = std::mem::take(&mut self.define_opaque);
|
||||
let trait_map = std::mem::take(&mut self.trait_map);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@ -618,7 +625,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let num_nodes = self.item_local_id_counter.as_usize();
|
||||
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
|
||||
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
|
||||
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
|
||||
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };
|
||||
|
||||
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -39,6 +39,7 @@ mod compile_error;
|
||||
mod concat;
|
||||
mod concat_bytes;
|
||||
mod concat_idents;
|
||||
mod define_opaque;
|
||||
mod derive;
|
||||
mod deriving;
|
||||
mod edition_panic;
|
||||
@ -114,6 +115,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
bench: test::expand_bench,
|
||||
cfg_accessible: cfg_accessible::Expander,
|
||||
cfg_eval: cfg_eval::expand,
|
||||
define_opaque: define_opaque::expand,
|
||||
derive: derive::Expander { is_const: false },
|
||||
derive_const: derive::Expander { is_const: true },
|
||||
global_allocator: global_allocator::expand,
|
||||
|
@ -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 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()
|
||||
}
|
||||
|
@ -209,6 +209,7 @@ pub type LazyFallbackBundle = Arc<LazyLock<FluentBundle, impl FnOnce() -> Fluent
|
||||
|
||||
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
|
||||
#[instrument(level = "trace", skip(resources))]
|
||||
#[cfg_attr(not(bootstrap), define_opaque(LazyFallbackBundle))]
|
||||
pub fn fallback_fluent_bundle(
|
||||
resources: Vec<&'static str>,
|
||||
with_directionality_markers: bool,
|
||||
|
@ -780,8 +780,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let guar = err.emit();
|
||||
fragment_kind.dummy(span, guar)
|
||||
let _guar = err.emit();
|
||||
fragment_kind.expect_from_annotatables(iter::once(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1307,13 +1307,18 @@ impl Attribute {
|
||||
#[derive(Debug)]
|
||||
pub struct AttributeMap<'tcx> {
|
||||
pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
|
||||
/// Preprocessed `#[define_opaque]` attribute.
|
||||
pub define_opaque: Option<&'tcx [(Span, LocalDefId)]>,
|
||||
// Only present when the crate hash is needed.
|
||||
pub opt_hash: Option<Fingerprint>,
|
||||
}
|
||||
|
||||
impl<'tcx> AttributeMap<'tcx> {
|
||||
pub const EMPTY: &'static AttributeMap<'static> =
|
||||
&AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) };
|
||||
pub const EMPTY: &'static AttributeMap<'static> = &AttributeMap {
|
||||
map: SortedMap::new(),
|
||||
opt_hash: Some(Fingerprint::ZERO),
|
||||
define_opaque: None,
|
||||
};
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
|
||||
|
@ -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,32 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks the `#[define_opaque]` attributes on items and collectes opaques to define
|
||||
/// from the referenced types.
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn collect_taits_from_defines_attr(&mut self) {
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(self.item);
|
||||
if !hir_id.is_owner() {
|
||||
return;
|
||||
}
|
||||
let Some(defines) = self.tcx.hir_attrs(hir_id.owner).define_opaque else {
|
||||
return;
|
||||
};
|
||||
for &(span, define) in defines {
|
||||
trace!(?define);
|
||||
let mode = std::mem::replace(&mut self.mode, CollectionMode::Taits);
|
||||
let n = self.opaques.len();
|
||||
super::sig_types::walk_types(self.tcx, define, self);
|
||||
if n == self.opaques.len() {
|
||||
self.tcx.dcx().span_err(span, "item does not contain any opaque types");
|
||||
}
|
||||
self.mode = mode;
|
||||
}
|
||||
// Allow using `#[define_opaque]` on assoc methods and type aliases to override the default collection mode in
|
||||
// case it was capturing too much.
|
||||
self.mode = CollectionMode::RpitAndAsyncFnOnly;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
|
||||
@ -210,6 +222,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
||||
self.visit_opaque_ty(alias_ty);
|
||||
}
|
||||
// Skips type aliases, as they are meant to be transparent.
|
||||
// FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly?
|
||||
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
|
||||
self.tcx
|
||||
.type_of(alias_ty.def_id)
|
||||
@ -283,28 +296,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
||||
self.visit_opaque_ty(alias_ty);
|
||||
}
|
||||
}
|
||||
ty::Adt(def, _) if def.did().is_local() => {
|
||||
if let CollectionMode::ImplTraitInAssocTypes = self.mode {
|
||||
return;
|
||||
}
|
||||
if !self.seen.insert(def.did().expect_local()) {
|
||||
return;
|
||||
}
|
||||
for variant in def.variants().iter() {
|
||||
for field in variant.fields.iter() {
|
||||
// Don't use the `ty::Adt` args, we either
|
||||
// * found the opaque in the args
|
||||
// * will find the opaque in the uninstantiated fields
|
||||
// The only other situation that can occur is that after instantiating,
|
||||
// some projection resolves to an opaque that we would have otherwise
|
||||
// not found. While we could instantiate and walk those, that would mean we
|
||||
// would have to walk all generic parameters of an Adt, which can quickly
|
||||
// degenerate into looking at an exponential number of types.
|
||||
let ty = self.tcx.type_of(field.did).instantiate_identity();
|
||||
self.visit_spanned(self.tcx.def_span(field.did), ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => trace!(kind=?t.kind()),
|
||||
}
|
||||
}
|
||||
@ -317,7 +308,9 @@ fn opaque_types_defined_by<'tcx>(
|
||||
let kind = tcx.def_kind(item);
|
||||
trace!(?kind);
|
||||
let mut collector = OpaqueTypeCollector::new(tcx, item);
|
||||
collector.collect_taits_from_defines_attr();
|
||||
super::sig_types::walk_types(tcx, item, &mut collector);
|
||||
|
||||
match kind {
|
||||
DefKind::AssocFn
|
||||
| DefKind::Fn
|
||||
@ -350,8 +343,7 @@ fn opaque_types_defined_by<'tcx>(
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::SyntheticCoroutineBody => {}
|
||||
// Closures and coroutines are type checked with their parent, so we need to allow all
|
||||
// opaques from the closure signature *and* from the parent body.
|
||||
// Closures and coroutines are type checked with their parent
|
||||
DefKind::Closure | DefKind::InlineConst => {
|
||||
collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user