fix name resolution for param defaults
This commit is contained in:
@@ -555,18 +555,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
// provide previous type parameters as they're built. We
|
||||
// put all the parameters on the ban list and then remove
|
||||
// them one by one as they are processed and become available.
|
||||
let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
|
||||
let mut found_default = false;
|
||||
default_ban_rib.bindings.extend(generics.params.iter().filter_map(
|
||||
|param| match param.kind {
|
||||
GenericParamKind::Type { default: Some(_), .. }
|
||||
| GenericParamKind::Const { default: Some(_), .. } => {
|
||||
found_default = true;
|
||||
Some((Ident::with_dummy_span(param.ident.name), Res::Err))
|
||||
let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
|
||||
let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
|
||||
for param in generics.params.iter() {
|
||||
match param.kind {
|
||||
GenericParamKind::Type { .. } => {
|
||||
forward_ty_ban_rib
|
||||
.bindings
|
||||
.insert(Ident::with_dummy_span(param.ident.name), Res::Err);
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
));
|
||||
GenericParamKind::Const { .. } => {
|
||||
forward_const_ban_rib
|
||||
.bindings
|
||||
.insert(Ident::with_dummy_span(param.ident.name), Res::Err);
|
||||
}
|
||||
GenericParamKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
|
||||
// rust-lang/rust#61631: The type `Self` is essentially
|
||||
// another type parameter. For ADTs, we consider it
|
||||
@@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
// such as in the case of `trait Add<Rhs = Self>`.)
|
||||
if self.diagnostic_metadata.current_self_item.is_some() {
|
||||
// (`Some` if + only if we are in ADT's generics.)
|
||||
default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
|
||||
forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
|
||||
}
|
||||
|
||||
for param in &generics.params {
|
||||
@@ -591,32 +596,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
}
|
||||
|
||||
if let Some(ref ty) = default {
|
||||
self.ribs[TypeNS].push(default_ban_rib);
|
||||
self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| {
|
||||
// HACK: We use an empty `ForwardGenericParamBanRibKind` here which
|
||||
// is only used to forbid the use of const parameters inside of
|
||||
// type defaults.
|
||||
//
|
||||
// While the rib name doesn't really fit here, it does allow us to use the same
|
||||
// code for both const and type parameters.
|
||||
this.visit_ty(ty);
|
||||
});
|
||||
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
|
||||
self.ribs[TypeNS].push(forward_ty_ban_rib);
|
||||
self.ribs[ValueNS].push(forward_const_ban_rib);
|
||||
self.visit_ty(ty);
|
||||
forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
|
||||
forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
|
||||
}
|
||||
|
||||
// Allow all following defaults to refer to this type parameter.
|
||||
default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
|
||||
forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
|
||||
}
|
||||
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
|
||||
// FIXME(const_generics_defaults): handle `default` value here
|
||||
for bound in ¶m.bounds {
|
||||
self.visit_param_bound(bound);
|
||||
}
|
||||
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
|
||||
// Const parameters can't have param bounds.
|
||||
assert!(param.bounds.is_empty());
|
||||
|
||||
self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
|
||||
self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
|
||||
self.visit_ty(ty);
|
||||
self.ribs[TypeNS].pop().unwrap();
|
||||
self.ribs[ValueNS].pop().unwrap();
|
||||
|
||||
if let Some(ref expr) = default {
|
||||
self.ribs[TypeNS].push(forward_ty_ban_rib);
|
||||
self.ribs[ValueNS].push(forward_const_ban_rib);
|
||||
self.visit_anon_const(expr);
|
||||
forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
|
||||
forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
|
||||
}
|
||||
|
||||
// Allow all following defaults to refer to this const parameter.
|
||||
forward_const_ban_rib
|
||||
.bindings
|
||||
.remove(&Ident::with_dummy_span(param.ident.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user