mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Only walk ribs to collect possibly shadowed params if we are adding params in our new rib
This commit is contained in:
parent
5367673014
commit
abada5fdca
@ -2667,119 +2667,128 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||
let mut function_type_rib = Rib::new(kind);
|
||||
let mut function_value_rib = Rib::new(kind);
|
||||
let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
|
||||
let mut seen_bindings = FxHashMap::default();
|
||||
// Store all seen lifetimes names from outer scopes.
|
||||
let mut seen_lifetimes = FxHashSet::default();
|
||||
|
||||
// We also can't shadow bindings from associated parent items.
|
||||
for ns in [ValueNS, TypeNS] {
|
||||
for parent_rib in self.ribs[ns].iter().rev() {
|
||||
seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
|
||||
// Only check for shadowed bindings if we're declaring new params.
|
||||
if !params.is_empty() {
|
||||
let mut seen_bindings = FxHashMap::default();
|
||||
// Store all seen lifetimes names from outer scopes.
|
||||
let mut seen_lifetimes = FxHashSet::default();
|
||||
|
||||
// Break at mod level, to account for nested items which are
|
||||
// allowed to shadow generic param names.
|
||||
if matches!(parent_rib.kind, RibKind::Module(..)) {
|
||||
// We also can't shadow bindings from associated parent items.
|
||||
for ns in [ValueNS, TypeNS] {
|
||||
for parent_rib in self.ribs[ns].iter().rev() {
|
||||
seen_bindings
|
||||
.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
|
||||
|
||||
// Break at mod level, to account for nested items which are
|
||||
// allowed to shadow generic param names.
|
||||
if matches!(parent_rib.kind, RibKind::Module(..)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forbid shadowing lifetime bindings
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
|
||||
if let LifetimeRibKind::Item = rib.kind {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forbid shadowing lifetime bindings
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
|
||||
if let LifetimeRibKind::Item = rib.kind {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for param in params {
|
||||
let ident = param.ident.normalize_to_macros_2_0();
|
||||
debug!("with_generic_param_rib: {}", param.id);
|
||||
|
||||
for param in params {
|
||||
let ident = param.ident.normalize_to_macros_2_0();
|
||||
debug!("with_generic_param_rib: {}", param.id);
|
||||
|
||||
if let GenericParamKind::Lifetime = param.kind
|
||||
&& let Some(&original) = seen_lifetimes.get(&ident)
|
||||
{
|
||||
diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
match seen_bindings.entry(ident) {
|
||||
Entry::Occupied(entry) => {
|
||||
let span = *entry.get();
|
||||
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
|
||||
self.report_error(param.ident.span, err);
|
||||
let rib = match param.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
GenericParamKind::Type { .. } => &mut function_type_rib,
|
||||
GenericParamKind::Const { .. } => &mut function_value_rib,
|
||||
};
|
||||
|
||||
// Taint the resolution in case of errors to prevent follow up errors in typeck
|
||||
self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
|
||||
rib.bindings.insert(ident, Res::Err);
|
||||
if let GenericParamKind::Lifetime = param.kind
|
||||
&& let Some(&original) = seen_lifetimes.get(&ident)
|
||||
{
|
||||
diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(param.ident.span);
|
||||
}
|
||||
}
|
||||
|
||||
if param.ident.name == kw::UnderscoreLifetime {
|
||||
self.r
|
||||
.dcx()
|
||||
.emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
match seen_bindings.entry(ident) {
|
||||
Entry::Occupied(entry) => {
|
||||
let span = *entry.get();
|
||||
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
|
||||
self.report_error(param.ident.span, err);
|
||||
let rib = match param.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
GenericParamKind::Type { .. } => &mut function_type_rib,
|
||||
GenericParamKind::Const { .. } => &mut function_value_rib,
|
||||
};
|
||||
|
||||
if param.ident.name == kw::StaticLifetime {
|
||||
self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
|
||||
span: param.ident.span,
|
||||
lifetime: param.ident,
|
||||
});
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
let def_id = self.r.local_def_id(param.id);
|
||||
|
||||
// Plain insert (no renaming).
|
||||
let (rib, def_kind) = match param.kind {
|
||||
GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
|
||||
GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
|
||||
GenericParamKind::Lifetime => {
|
||||
let res = LifetimeRes::Param { param: def_id, binder };
|
||||
self.record_lifetime_param(param.id, res);
|
||||
function_lifetime_rib.bindings.insert(ident, (param.id, res));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let res = match kind {
|
||||
RibKind::Item(..) | RibKind::AssocItem => Res::Def(def_kind, def_id.to_def_id()),
|
||||
RibKind::Normal => {
|
||||
// FIXME(non_lifetime_binders): Stop special-casing
|
||||
// const params to error out here.
|
||||
if self.r.tcx.features().non_lifetime_binders
|
||||
&& matches!(param.kind, GenericParamKind::Type { .. })
|
||||
{
|
||||
Res::Def(def_kind, def_id.to_def_id())
|
||||
} else {
|
||||
Res::Err
|
||||
// Taint the resolution in case of errors to prevent follow up errors in typeck
|
||||
self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
|
||||
rib.bindings.insert(ident, Res::Err);
|
||||
continue;
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(param.ident.span);
|
||||
}
|
||||
}
|
||||
_ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
|
||||
};
|
||||
self.r.record_partial_res(param.id, PartialRes::new(res));
|
||||
rib.bindings.insert(ident, res);
|
||||
|
||||
if param.ident.name == kw::UnderscoreLifetime {
|
||||
self.r
|
||||
.dcx()
|
||||
.emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
if param.ident.name == kw::StaticLifetime {
|
||||
self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
|
||||
span: param.ident.span,
|
||||
lifetime: param.ident,
|
||||
});
|
||||
// Record lifetime res, so lowering knows there is something fishy.
|
||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
let def_id = self.r.local_def_id(param.id);
|
||||
|
||||
// Plain insert (no renaming).
|
||||
let (rib, def_kind) = match param.kind {
|
||||
GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
|
||||
GenericParamKind::Const { .. } => {
|
||||
(&mut function_value_rib, DefKind::ConstParam)
|
||||
}
|
||||
GenericParamKind::Lifetime => {
|
||||
let res = LifetimeRes::Param { param: def_id, binder };
|
||||
self.record_lifetime_param(param.id, res);
|
||||
function_lifetime_rib.bindings.insert(ident, (param.id, res));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let res = match kind {
|
||||
RibKind::Item(..) | RibKind::AssocItem => {
|
||||
Res::Def(def_kind, def_id.to_def_id())
|
||||
}
|
||||
RibKind::Normal => {
|
||||
// FIXME(non_lifetime_binders): Stop special-casing
|
||||
// const params to error out here.
|
||||
if self.r.tcx.features().non_lifetime_binders
|
||||
&& matches!(param.kind, GenericParamKind::Type { .. })
|
||||
{
|
||||
Res::Def(def_kind, def_id.to_def_id())
|
||||
} else {
|
||||
Res::Err
|
||||
}
|
||||
}
|
||||
_ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
|
||||
};
|
||||
self.r.record_partial_res(param.id, PartialRes::new(res));
|
||||
rib.bindings.insert(ident, res);
|
||||
}
|
||||
}
|
||||
|
||||
self.lifetime_ribs.push(function_lifetime_rib);
|
||||
|
Loading…
Reference in New Issue
Block a user