1
Fork 0

Make def_key and HIR parenting consistent.

This commit is contained in:
Camille GILLOT 2021-02-13 20:41:02 +01:00
parent 17a07d71bf
commit 445b4e379c
11 changed files with 177 additions and 54 deletions

View file

@ -223,7 +223,7 @@ enum ImplTraitContext<'b, 'a> {
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`. /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
/// ///
/// Newly generated parameters should be inserted into the given `Vec`. /// Newly generated parameters should be inserted into the given `Vec`.
Universal(&'b mut Vec<hir::GenericParam<'a>>), Universal(&'b mut Vec<hir::GenericParam<'a>>, LocalDefId),
/// Treat `impl Trait` as shorthand for a new opaque type. /// Treat `impl Trait` as shorthand for a new opaque type.
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
@ -278,7 +278,7 @@ impl<'a> ImplTraitContext<'_, 'a> {
fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'a> { fn reborrow<'this>(&'this mut self) -> ImplTraitContext<'this, 'a> {
use self::ImplTraitContext::*; use self::ImplTraitContext::*;
match self { match self {
Universal(params) => Universal(params), Universal(params, parent) => Universal(params, *parent),
ReturnPositionOpaqueTy { fn_def_id, origin } => { ReturnPositionOpaqueTy { fn_def_id, origin } => {
ReturnPositionOpaqueTy { fn_def_id: *fn_def_id, origin: *origin } ReturnPositionOpaqueTy { fn_def_id: *fn_def_id, origin: *origin }
} }
@ -475,25 +475,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
impl MiscCollector<'_, '_, '_> { impl MiscCollector<'_, '_, '_> {
fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: LocalDefId) { fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) {
match tree.kind { match tree.kind {
UseTreeKind::Simple(_, id1, id2) => { UseTreeKind::Simple(_, id1, id2) => {
for &id in &[id1, id2] { for &id in &[id1, id2] {
self.lctx.resolver.create_def(
owner,
id,
DefPathData::Misc,
ExpnId::root(),
tree.prefix.span,
);
self.lctx.allocate_hir_id_counter(id); self.lctx.allocate_hir_id_counter(id);
} }
} }
UseTreeKind::Glob => (), UseTreeKind::Glob => (),
UseTreeKind::Nested(ref trees) => { UseTreeKind::Nested(ref trees) => {
for &(ref use_tree, id) in trees { for &(ref use_tree, id) in trees {
let hir_id = self.lctx.allocate_hir_id_counter(id); self.lctx.allocate_hir_id_counter(id);
self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); self.allocate_use_tree_hir_id_counters(use_tree);
} }
} }
} }
@ -502,7 +495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> { impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
fn visit_item(&mut self, item: &'tcx Item) { fn visit_item(&mut self, item: &'tcx Item) {
let hir_id = self.lctx.allocate_hir_id_counter(item.id); self.lctx.allocate_hir_id_counter(item.id);
match item.kind { match item.kind {
ItemKind::Struct(_, ref generics) ItemKind::Struct(_, ref generics)
@ -521,7 +514,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count); self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count);
} }
ItemKind::Use(ref use_tree) => { ItemKind::Use(ref use_tree) => {
self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); self.allocate_use_tree_hir_id_counters(use_tree);
} }
_ => {} _ => {}
} }
@ -939,8 +932,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// `lifetimes_to_define`. If we swapped the order of these two, // `lifetimes_to_define`. If we swapped the order of these two,
// in-band-lifetimes introduced by generics or where-clauses // in-band-lifetimes introduced by generics or where-clauses
// wouldn't have been added yet. // wouldn't have been added yet.
let generics = let generics = this.lower_generics_mut(
this.lower_generics_mut(generics, ImplTraitContext::Universal(&mut params)); generics,
ImplTraitContext::Universal(
&mut params,
this.current_hir_id_owner.last().unwrap().0,
),
);
let res = f(this, &mut params); let res = f(this, &mut params);
(params, (generics, res)) (params, (generics, res))
}) })
@ -1145,6 +1143,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
AssocTyConstraintKind::Bound { ref bounds } => { AssocTyConstraintKind::Bound { ref bounds } => {
let mut capturable_lifetimes; let mut capturable_lifetimes;
let mut parent_def_id = self.current_hir_id_owner.last().unwrap().0;
// Piggy-back on the `impl Trait` context to figure out the correct behavior. // Piggy-back on the `impl Trait` context to figure out the correct behavior.
let (desugar_to_impl_trait, itctx) = match itctx { let (desugar_to_impl_trait, itctx) = match itctx {
// We are in the return position: // We are in the return position:
@ -1164,7 +1163,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// so desugar to // so desugar to
// //
// fn foo(x: dyn Iterator<Item = impl Debug>) // fn foo(x: dyn Iterator<Item = impl Debug>)
ImplTraitContext::Universal(..) if self.is_in_dyn_type => (true, itctx), ImplTraitContext::Universal(_, parent) if self.is_in_dyn_type => {
parent_def_id = parent;
(true, itctx)
}
// In `type Foo = dyn Iterator<Item: Debug>` we desugar to // In `type Foo = dyn Iterator<Item: Debug>` we desugar to
// `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the
@ -1198,7 +1200,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// constructing the HIR for `impl bounds...` and then lowering that. // constructing the HIR for `impl bounds...` and then lowering that.
let impl_trait_node_id = self.resolver.next_node_id(); let impl_trait_node_id = self.resolver.next_node_id();
let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
self.resolver.create_def( self.resolver.create_def(
parent_def_id, parent_def_id,
impl_trait_node_id, impl_trait_node_id,
@ -1451,7 +1452,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|this| this.lower_param_bounds(bounds, nested_itctx), |this| this.lower_param_bounds(bounds, nested_itctx),
) )
} }
ImplTraitContext::Universal(in_band_ty_params) => { ImplTraitContext::Universal(in_band_ty_params, parent_def_id) => {
// Add a definition for the in-band `Param`. // Add a definition for the in-band `Param`.
let def_id = self.resolver.local_def_id(def_node_id); let def_id = self.resolver.local_def_id(def_node_id);
@ -1460,7 +1461,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let hir_bounds = self.with_hir_id_owner(def_node_id, |this| { let hir_bounds = self.with_hir_id_owner(def_node_id, |this| {
this.lower_param_bounds( this.lower_param_bounds(
bounds, bounds,
ImplTraitContext::Universal(in_band_ty_params), ImplTraitContext::Universal(in_band_ty_params, parent_def_id),
) )
}); });
// Set the name to `impl Bound1 + Bound2`. // Set the name to `impl Bound1 + Bound2`.
@ -1891,7 +1892,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
this.arena.alloc_from_iter(inputs.iter().map(|param| { this.arena.alloc_from_iter(inputs.iter().map(|param| {
if let Some((_, ibty)) = &mut in_band_ty_params { if let Some((_, ibty)) = &mut in_band_ty_params {
this.lower_ty_direct(&param.ty, ImplTraitContext::Universal(ibty)) this.lower_ty_direct(
&param.ty,
ImplTraitContext::Universal(
ibty,
this.current_hir_id_owner.last().unwrap().0,
),
)
} else { } else {
this.lower_ty_direct(&param.ty, ImplTraitContext::disallowed()) this.lower_ty_direct(&param.ty, ImplTraitContext::disallowed())
} }

View file

@ -221,6 +221,18 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
data.signature = data.signature =
Some(self.arena.alloc(Owner { parent: entry.parent, node: entry.node })); Some(self.arena.alloc(Owner { parent: entry.parent, node: entry.node }));
let dk_parent = self.definitions.def_key(id.owner).parent;
if let Some(dk_parent) = dk_parent {
let dk_parent = LocalDefId { local_def_index: dk_parent };
let dk_parent = self.definitions.local_def_id_to_hir_id(dk_parent);
if dk_parent.owner != entry.parent.owner {
panic!(
"Different parents for {:?} => dk_parent={:?} actual={:?}",
id.owner, dk_parent, entry.parent,
)
}
}
} else { } else {
assert_eq!(entry.parent.owner, id.owner); assert_eq!(entry.parent.owner, id.owner);
insert_vec_map( insert_vec_map(

View file

@ -1,4 +1,4 @@
use crate::Resolver; use crate::{ImplTraitContext, Resolver};
use rustc_ast::visit::{self, FnKind}; use rustc_ast::visit::{self, FnKind};
use rustc_ast::walk_list; use rustc_ast::walk_list;
use rustc_ast::*; use rustc_ast::*;
@ -16,14 +16,15 @@ crate fn collect_definitions(
fragment: &AstFragment, fragment: &AstFragment,
expansion: ExpnId, expansion: ExpnId,
) { ) {
let parent_def = resolver.invocation_parents[&expansion]; let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion];
fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion }); fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context });
} }
/// Creates `DefId`s for nodes in the AST. /// Creates `DefId`s for nodes in the AST.
struct DefCollector<'a, 'b> { struct DefCollector<'a, 'b> {
resolver: &'a mut Resolver<'b>, resolver: &'a mut Resolver<'b>,
parent_def: LocalDefId, parent_def: LocalDefId,
impl_trait_context: ImplTraitContext,
expansion: ExpnId, expansion: ExpnId,
} }
@ -40,6 +41,16 @@ impl<'a, 'b> DefCollector<'a, 'b> {
self.parent_def = orig_parent_def; self.parent_def = orig_parent_def;
} }
fn with_impl_trait<F: FnOnce(&mut Self)>(
&mut self,
impl_trait_context: ImplTraitContext,
f: F,
) {
let orig_itc = std::mem::replace(&mut self.impl_trait_context, impl_trait_context);
f(self);
self.impl_trait_context = orig_itc;
}
fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) { fn collect_field(&mut self, field: &'a StructField, index: Option<usize>) {
let index = |this: &Self| { let index = |this: &Self| {
index.unwrap_or_else(|| { index.unwrap_or_else(|| {
@ -60,8 +71,9 @@ impl<'a, 'b> DefCollector<'a, 'b> {
} }
fn visit_macro_invoc(&mut self, id: NodeId) { fn visit_macro_invoc(&mut self, id: NodeId) {
let id = id.placeholder_to_expn_id();
let old_parent = let old_parent =
self.resolver.invocation_parents.insert(id.placeholder_to_expn_id(), self.parent_def); self.resolver.invocation_parents.insert(id, (self.parent_def, self.impl_trait_context));
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
} }
} }
@ -103,29 +115,37 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
let def = self.create_def(i.id, def_data, i.span); let def = self.create_def(i.id, def_data, i.span);
self.with_parent(def, |this| { self.with_parent(def, |this| {
match i.kind { this.with_impl_trait(ImplTraitContext::Existential, |this| {
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { match i.kind {
// If this is a unit or tuple-like struct, register the constructor. ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
if let Some(ctor_hir_id) = struct_def.ctor_id() { // If this is a unit or tuple-like struct, register the constructor.
this.create_def(ctor_hir_id, DefPathData::Ctor, i.span); if let Some(ctor_hir_id) = struct_def.ctor_id() {
this.create_def(ctor_hir_id, DefPathData::Ctor, i.span);
}
} }
_ => {}
} }
_ => {} visit::walk_item(this, i);
} })
visit::walk_item(this, i);
}); });
} }
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let FnKind::Fn(_, _, sig, _, body) = fn_kind { if let FnKind::Fn(_, _, sig, _, body) = fn_kind {
if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness { if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness {
self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); let return_impl_trait_id =
self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
// For async functions, we need to create their inner defs inside of a // For async functions, we need to create their inner defs inside of a
// closure to match their desugared representation. Besides that, // closure to match their desugared representation. Besides that,
// we must mirror everything that `visit::walk_fn` below does. // we must mirror everything that `visit::walk_fn` below does.
self.visit_fn_header(&sig.header); self.visit_fn_header(&sig.header);
visit::walk_fn_decl(self, &sig.decl); for param in &sig.decl.inputs {
self.visit_param(param);
}
self.with_parent(return_impl_trait_id, |this| {
this.visit_fn_ret_ty(&sig.decl.output)
});
let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
self.with_parent(closure_def, |this| walk_list!(this, visit_block, body)); self.with_parent(closure_def, |this| walk_list!(this, visit_block, body));
return; return;
@ -137,6 +157,14 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
self.create_def(id, DefPathData::Misc, use_tree.span); self.create_def(id, DefPathData::Misc, use_tree.span);
match use_tree.kind {
UseTreeKind::Simple(_, id1, id2) => {
self.create_def(id1, DefPathData::Misc, use_tree.prefix.span);
self.create_def(id2, DefPathData::Misc, use_tree.prefix.span);
}
UseTreeKind::Glob => (),
UseTreeKind::Nested(..) => {}
}
visit::walk_use_tree(self, use_tree, id); visit::walk_use_tree(self, use_tree, id);
} }
@ -191,7 +219,15 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
}; };
self.create_def(param.id, def_path_data, param.ident.span); self.create_def(param.id, def_path_data, param.ident.span);
visit::walk_generic_param(self, param); // impl-Trait can happen inside generic parameters, like
// ```
// fn foo<U: Iterator<Item = impl Clone>>() {}
// ```
//
// In that case, the impl-trait is lowered as an additional generic parameter.
self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| {
visit::walk_generic_param(this, param)
});
} }
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
@ -244,8 +280,19 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
match ty.kind { match ty.kind {
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
TyKind::ImplTrait(node_id, _) => { TyKind::ImplTrait(node_id, _) => {
let parent_def = self.create_def(node_id, DefPathData::ImplTrait, ty.span); let parent_def = match self.impl_trait_context {
self.with_parent(parent_def, |this| visit::walk_ty(this, ty)); ImplTraitContext::Universal(item_def) => self.resolver.create_def(
item_def,
node_id,
DefPathData::ImplTrait,
self.expansion,
ty.span,
),
ImplTraitContext::Existential => {
self.create_def(node_id, DefPathData::ImplTrait, ty.span)
}
};
self.with_parent(parent_def, |this| visit::walk_ty(this, ty))
} }
_ => visit::walk_ty(self, ty), _ => visit::walk_ty(self, ty),
} }
@ -275,7 +322,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
} }
fn visit_param(&mut self, p: &'a Param) { fn visit_param(&mut self, p: &'a Param) {
if p.is_placeholder { self.visit_macro_invoc(p.id) } else { visit::walk_param(self, p) } if p.is_placeholder {
self.visit_macro_invoc(p.id)
} else {
self.with_impl_trait(ImplTraitContext::Universal(self.parent_def), |this| {
visit::walk_param(this, p)
})
}
} }
// This method is called only when we are visiting an individual field // This method is called only when we are visiting an individual field

View file

@ -156,6 +156,12 @@ impl<'a> ParentScope<'a> {
} }
} }
#[derive(Copy, Debug, Clone)]
enum ImplTraitContext {
Existential,
Universal(LocalDefId),
}
#[derive(Eq)] #[derive(Eq)]
struct BindingError { struct BindingError {
name: Symbol, name: Symbol,
@ -989,8 +995,9 @@ pub struct Resolver<'a> {
/// Indices of unnamed struct or variant fields with unresolved attributes. /// Indices of unnamed struct or variant fields with unresolved attributes.
placeholder_field_indices: FxHashMap<NodeId, usize>, placeholder_field_indices: FxHashMap<NodeId, usize>,
/// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
/// we know what parent node that fragment should be attached to thanks to this table. /// we know what parent node that fragment should be attached to thanks to this table,
invocation_parents: FxHashMap<ExpnId, LocalDefId>, /// and how the `impl Trait` fragments were introduced.
invocation_parents: FxHashMap<ExpnId, (LocalDefId, ImplTraitContext)>,
next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
/// Some way to know that we are in a *trait* impl in `visit_assoc_item`. /// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
@ -1205,7 +1212,7 @@ impl<'a> Resolver<'a> {
node_id_to_def_id.insert(CRATE_NODE_ID, root); node_id_to_def_id.insert(CRATE_NODE_ID, root);
let mut invocation_parents = FxHashMap::default(); let mut invocation_parents = FxHashMap::default();
invocation_parents.insert(ExpnId::root(), root); invocation_parents.insert(ExpnId::root(), (root, ImplTraitContext::Existential));
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
.opts .opts

View file

@ -326,7 +326,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
// nearest closing item - we should try to return the closest parent of the ExpnId // nearest closing item - we should try to return the closest parent of the ExpnId
self.invocation_parents self.invocation_parents
.get(&expn_id) .get(&expn_id)
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[*id]) .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0])
} }
fn has_derive_copy(&self, expn_id: ExpnId) -> bool { fn has_derive_copy(&self, expn_id: ExpnId) -> bool {

View file

@ -93,9 +93,6 @@
59| 1| used_only_from_this_lib_crate_generic_function(some_vec); 59| 1| used_only_from_this_lib_crate_generic_function(some_vec);
60| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); 60| 1| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
61| 1|} 61| 1|}
------------------
| Unexecuted instantiation: used_crate::use_this_lib_crate
------------------
62| | 62| |
63| |// FIXME(#79651): `used_from_bin_crate_and_lib_crate_generic_function()` is covered and executed 63| |// FIXME(#79651): `used_from_bin_crate_and_lib_crate_generic_function()` is covered and executed
64| |// `2` times, but the coverage output also shows (at the bottom of the coverage report): 64| |// `2` times, but the coverage output also shows (at the bottom of the coverage report):

View file

@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer
--> $DIR/tls.rs:12:25 --> $DIR/tls.rs:12:25
| |
LL | unsafe { let _val = A; } LL | unsafe { let _val = A; }
| ^ cannot access thread local static (DefId(0:4 ~ tls[317d]::A)) | ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
error[E0080]: could not evaluate static initializer error[E0080]: could not evaluate static initializer
--> $DIR/tls.rs:19:26 --> $DIR/tls.rs:19:26
| |
LL | unsafe { let _val = &A; } LL | unsafe { let _val = &A; }
| ^ cannot access thread local static (DefId(0:4 ~ tls[317d]::A)) | ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
warning: skipping const checks warning: skipping const checks
| |

View file

@ -12,7 +12,7 @@ note: generator is not `Send` as this value is used across a yield
--> $DIR/generator-print-verbose-1.rs:35:9 --> $DIR/generator-print-verbose-1.rs:35:9
| |
LL | let _non_send_gen = make_non_send_generator(); LL | let _non_send_gen = make_non_send_generator();
| ------------- has type `Opaque(DefId(0:24 ~ generator_print_verbose_1[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send` | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
LL | yield; LL | yield;
| ^^^^^ yield occurs here, with `_non_send_gen` maybe used later | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
LL | }; LL | };
@ -30,10 +30,10 @@ LL | require_send(send_gen);
= help: the trait `Sync` is not implemented for `RefCell<i32>` = help: the trait `Sync` is not implemented for `RefCell<i32>`
= note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>` = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
= note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]` = note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
= note: required because it appears within the type `Opaque(DefId(0:29 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])` = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
= note: required because it appears within the type `Opaque(DefId(0:32 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])` = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])`
= note: required because it appears within the type `{Opaque(DefId(0:32 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}` = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}`
= note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:32 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]` = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -0,0 +1,20 @@
use std::fmt::Debug;
macro_rules! i {
($($tr:tt)*) => { impl $($tr)* };
}
fn foo(x: i!(Debug), y: i!(Debug)) -> String {
let mut a = x;
a = y; //~ ERROR mismatched
format!("{:?}", a)
}
trait S<T> {}
fn much_universe<T: S<i!(Debug)>, U: IntoIterator<Item = i!(Iterator<Item = i!(Clone)>)>>(
_: i!(Debug + Clone),
) {
}
fn main() {}

View file

@ -0,0 +1,20 @@
error[E0308]: mismatched types
--> $DIR/impl-trait-in-macro.rs:9:9
|
LL | ($($tr:tt)*) => { impl $($tr)* };
| ----
| |
| expected type parameter
| found type parameter
...
LL | a = y;
| ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
|
= note: expected type parameter `impl Debug` (type parameter `impl Debug`)
found type parameter `impl Debug` (type parameter `impl Debug`)
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -6,4 +6,11 @@ fn foo(x: impl Debug, y: impl Debug) -> String {
format!("{:?}", a) format!("{:?}", a)
} }
fn main() { } trait S<T> {}
fn much_universe<T: S<impl Debug>, U: IntoIterator<Item = impl Iterator<Item = impl Clone>>>(
_: impl Debug + Clone,
) {
}
fn main() {}