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
1 changed files with 109 additions and 100 deletions
|
@ -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_type_rib = Rib::new(kind);
|
||||||
let mut function_value_rib = Rib::new(kind);
|
let mut function_value_rib = Rib::new(kind);
|
||||||
let mut function_lifetime_rib = LifetimeRib::new(lifetime_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.
|
// Only check for shadowed bindings if we're declaring new params.
|
||||||
for ns in [ValueNS, TypeNS] {
|
if !params.is_empty() {
|
||||||
for parent_rib in self.ribs[ns].iter().rev() {
|
let mut seen_bindings = FxHashMap::default();
|
||||||
seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
|
// 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
|
// We also can't shadow bindings from associated parent items.
|
||||||
// allowed to shadow generic param names.
|
for ns in [ValueNS, TypeNS] {
|
||||||
if matches!(parent_rib.kind, RibKind::Module(..)) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Forbid shadowing lifetime bindings
|
for param in params {
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
let ident = param.ident.normalize_to_macros_2_0();
|
||||||
seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
|
debug!("with_generic_param_rib: {}", param.id);
|
||||||
if let LifetimeRibKind::Item = rib.kind {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for param in params {
|
if let GenericParamKind::Lifetime = param.kind
|
||||||
let ident = param.ident.normalize_to_macros_2_0();
|
&& let Some(&original) = seen_lifetimes.get(&ident)
|
||||||
debug!("with_generic_param_rib: {}", param.id);
|
{
|
||||||
|
diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
|
||||||
if let GenericParamKind::Lifetime = param.kind
|
// Record lifetime res, so lowering knows there is something fishy.
|
||||||
&& let Some(&original) = seen_lifetimes.get(&ident)
|
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
||||||
{
|
|
||||||
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);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
entry.insert(param.ident.span);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if param.ident.name == kw::UnderscoreLifetime {
|
match seen_bindings.entry(ident) {
|
||||||
self.r
|
Entry::Occupied(entry) => {
|
||||||
.dcx()
|
let span = *entry.get();
|
||||||
.emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
|
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
|
||||||
// Record lifetime res, so lowering knows there is something fishy.
|
self.report_error(param.ident.span, err);
|
||||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
let rib = match param.kind {
|
||||||
continue;
|
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 {
|
// Taint the resolution in case of errors to prevent follow up errors in typeck
|
||||||
self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
|
self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
|
||||||
span: param.ident.span,
|
rib.bindings.insert(ident, Res::Err);
|
||||||
lifetime: param.ident,
|
continue;
|
||||||
});
|
}
|
||||||
// Record lifetime res, so lowering knows there is something fishy.
|
Entry::Vacant(entry) => {
|
||||||
self.record_lifetime_param(param.id, LifetimeRes::Error);
|
entry.insert(param.ident.span);
|
||||||
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),
|
|
||||||
};
|
if param.ident.name == kw::UnderscoreLifetime {
|
||||||
self.r.record_partial_res(param.id, PartialRes::new(res));
|
self.r
|
||||||
rib.bindings.insert(ident, res);
|
.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);
|
self.lifetime_ribs.push(function_lifetime_rib);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue