-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Deriving: Include bound generic params in type parameters for where clause #89341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
f0e9982
e559867
34d95d9
87241e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -332,44 +332,74 @@ pub fn combine_substructure( | |
RefCell::new(f) | ||
} | ||
|
||
struct TypeParameter { | ||
bound_generic_params: Vec<ast::GenericParam>, | ||
ty: P<ast::Ty>, | ||
} | ||
|
||
/// This method helps to extract all the type parameters referenced from a | ||
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that | ||
/// is not global and starts with `T`, or a `TyQPath`. | ||
/// Also include bound generic params from the input type. | ||
fn find_type_parameters( | ||
ty: &ast::Ty, | ||
ty_param_names: &[Symbol], | ||
cx: &ExtCtxt<'_>, | ||
) -> Vec<P<ast::Ty>> { | ||
) -> Vec<TypeParameter> { | ||
use rustc_ast::visit; | ||
|
||
struct Visitor<'a, 'b> { | ||
cx: &'a ExtCtxt<'b>, | ||
ty_param_names: &'a [Symbol], | ||
types: Vec<P<ast::Ty>>, | ||
bound_generic_params_stack: Vec<ast::GenericParam>, | ||
type_params: Vec<TypeParameter>, | ||
} | ||
|
||
impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { | ||
fn visit_ty(&mut self, ty: &'a ast::Ty) { | ||
if let ast::TyKind::Path(_, ref path) = ty.kind { | ||
if let Some(segment) = path.segments.first() { | ||
if self.ty_param_names.contains(&segment.ident.name) { | ||
self.types.push(P(ty.clone())); | ||
self.type_params.push(TypeParameter { | ||
bound_generic_params: self.bound_generic_params_stack.clone(), | ||
ty: P(ty.clone()), | ||
}); | ||
} | ||
} | ||
} | ||
|
||
visit::walk_ty(self, ty) | ||
} | ||
|
||
// Place bound generic params on a stack, to extract them when a type is encountered. | ||
fn visit_poly_trait_ref( | ||
&mut self, | ||
trait_ref: &'a ast::PolyTraitRef, | ||
modifier: &'a ast::TraitBoundModifier, | ||
) { | ||
let stack_len = trait_ref.bound_generic_params.len(); | ||
self.bound_generic_params_stack | ||
.extend(trait_ref.bound_generic_params.clone().into_iter()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would probably break by HRTB variable shadowing, e.g.
by outputting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to come up with a test case where this might happen. But I'm unsure; I couldn't find one. |
||
|
||
visit::walk_poly_trait_ref(self, trait_ref, modifier); | ||
|
||
self.bound_generic_params_stack.truncate(stack_len); | ||
} | ||
|
||
fn visit_mac_call(&mut self, mac: &ast::MacCall) { | ||
self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros"); | ||
} | ||
} | ||
|
||
let mut visitor = Visitor { cx, ty_param_names, types: Vec::new() }; | ||
let mut visitor = Visitor { | ||
cx, | ||
ty_param_names, | ||
bound_generic_params_stack: Vec::new(), | ||
type_params: Vec::new(), | ||
}; | ||
visit::Visitor::visit_ty(&mut visitor, ty); | ||
|
||
visitor.types | ||
visitor.type_params | ||
} | ||
|
||
impl<'a> TraitDef<'a> { | ||
|
@@ -617,11 +647,11 @@ impl<'a> TraitDef<'a> { | |
ty_params.map(|ty_param| ty_param.ident.name).collect(); | ||
|
||
for field_ty in field_tys { | ||
let tys = find_type_parameters(&field_ty, &ty_param_names, cx); | ||
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx); | ||
|
||
for ty in tys { | ||
for field_ty_param in field_ty_params { | ||
// if we have already handled this type, skip it | ||
if let ast::TyKind::Path(_, ref p) = ty.kind { | ||
if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind { | ||
if p.segments.len() == 1 | ||
&& ty_param_names.contains(&p.segments[0].ident.name) | ||
{ | ||
|
@@ -639,8 +669,8 @@ impl<'a> TraitDef<'a> { | |
|
||
let predicate = ast::WhereBoundPredicate { | ||
span: self.span, | ||
bound_generic_params: Vec::new(), | ||
bounded_ty: ty, | ||
bound_generic_params: field_ty_param.bound_generic_params, | ||
bounded_ty: field_ty_param.ty, | ||
bounds, | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// check-pass | ||
|
||
#![feature(generic_associated_types)] | ||
|
||
trait CallWithShim: Sized { | ||
type Shim<'s> | ||
where | ||
Self: 's; | ||
} | ||
|
||
#[derive(Clone)] | ||
struct ShimMethod<T: CallWithShim + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>)); | ||
|
||
pub fn main() {} |
Uh oh!
There was an error while loading. Please reload this page.