resolve: prohibit foreign statics w/ generics
This commit modifies resolve to disallow foreign statics that use parent generics. `improper_ctypes` is not written to support type parameters, as these are normally disallowed before the lint is run. Thus, type parameters in foreign statics must be prohibited before the lint. The only other case where this *could* have occured is in functions, but typeck prohibits this with a "foreign items may not have type parameters" error - a similar error did not exist for statics, because statics cannot have type parameters, but they can use any type parameters that are in scope (which isn't the case for functions). Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
7870050796
commit
ccbf2b76a6
8 changed files with 263 additions and 178 deletions
|
@ -20,7 +20,7 @@ use syntax_pos::{BytePos, Span, MultiSpan};
|
||||||
|
|
||||||
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
|
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
|
||||||
use crate::{path_names_to_string, KNOWN_TOOLS};
|
use crate::{path_names_to_string, KNOWN_TOOLS};
|
||||||
use crate::{BindingError, CrateLint, LegacyScope, Module, ModuleOrUniformRoot};
|
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
|
||||||
use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
|
use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
|
||||||
|
|
||||||
type Res = def::Res<ast::NodeId>;
|
type Res = def::Res<ast::NodeId>;
|
||||||
|
@ -102,7 +102,7 @@ impl<'a> Resolver<'a> {
|
||||||
&self, span: Span, resolution_error: ResolutionError<'_>
|
&self, span: Span, resolution_error: ResolutionError<'_>
|
||||||
) -> DiagnosticBuilder<'_> {
|
) -> DiagnosticBuilder<'_> {
|
||||||
match resolution_error {
|
match resolution_error {
|
||||||
ResolutionError::GenericParamsFromOuterFunction(outer_res) => {
|
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
|
||||||
let mut err = struct_span_err!(self.session,
|
let mut err = struct_span_err!(self.session,
|
||||||
span,
|
span,
|
||||||
E0401,
|
E0401,
|
||||||
|
@ -148,22 +148,24 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to retrieve the span of the function signature and generate a new message
|
if has_generic_params == HasGenericParams::Yes {
|
||||||
// with a local type or const parameter.
|
// Try to retrieve the span of the function signature and generate a new
|
||||||
let sugg_msg = &format!("try using a local generic parameter instead");
|
// message with a local type or const parameter.
|
||||||
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
|
let sugg_msg = &format!("try using a local generic parameter instead");
|
||||||
// Suggest the modification to the user
|
if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) {
|
||||||
err.span_suggestion(
|
// Suggest the modification to the user
|
||||||
sugg_span,
|
err.span_suggestion(
|
||||||
sugg_msg,
|
sugg_span,
|
||||||
new_snippet,
|
sugg_msg,
|
||||||
Applicability::MachineApplicable,
|
snippet,
|
||||||
);
|
Applicability::MachineApplicable,
|
||||||
} else if let Some(sp) = cm.generate_fn_name_span(span) {
|
);
|
||||||
err.span_label(sp,
|
} else if let Some(sp) = cm.generate_fn_name_span(span) {
|
||||||
format!("try adding a local generic parameter in this method instead"));
|
err.span_label(sp,
|
||||||
} else {
|
format!("try adding a local generic parameter in this method instead"));
|
||||||
err.help(&format!("try using a local generic parameter instead"));
|
} else {
|
||||||
|
err.help(&format!("try using a local generic parameter instead"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err
|
err
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
//! If you wonder why there's no `early.rs`, that's because it's split into three files -
|
//! If you wonder why there's no `early.rs`, that's because it's split into three files -
|
||||||
//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`.
|
//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`.
|
||||||
|
|
||||||
use GenericParameters::*;
|
|
||||||
use RibKind::*;
|
use RibKind::*;
|
||||||
|
|
||||||
use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
|
use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding};
|
||||||
|
@ -46,16 +45,6 @@ struct BindingInfo {
|
||||||
binding_mode: BindingMode,
|
binding_mode: BindingMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
enum GenericParameters<'a, 'b> {
|
|
||||||
NoGenericParams,
|
|
||||||
HasGenericParams(// Type parameters.
|
|
||||||
&'b Generics,
|
|
||||||
|
|
||||||
// The kind of the rib used for type parameters.
|
|
||||||
RibKind<'a>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
enum PatternSource {
|
enum PatternSource {
|
||||||
Match,
|
Match,
|
||||||
|
@ -85,6 +74,10 @@ enum PatBoundCtx {
|
||||||
Or,
|
Or,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does this the item (from the item rib scope) allow generic parameters?
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
crate enum HasGenericParams { Yes, No }
|
||||||
|
|
||||||
/// The rib kind restricts certain accesses,
|
/// The rib kind restricts certain accesses,
|
||||||
/// e.g. to a `Res::Local` of an outer item.
|
/// e.g. to a `Res::Local` of an outer item.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -103,7 +96,7 @@ crate enum RibKind<'a> {
|
||||||
FnItemRibKind,
|
FnItemRibKind,
|
||||||
|
|
||||||
/// We passed through an item scope. Disallow upvars.
|
/// We passed through an item scope. Disallow upvars.
|
||||||
ItemRibKind,
|
ItemRibKind(HasGenericParams),
|
||||||
|
|
||||||
/// We're in a constant item. Can't refer to dynamic stuff.
|
/// We're in a constant item. Can't refer to dynamic stuff.
|
||||||
ConstantItemRibKind,
|
ConstantItemRibKind,
|
||||||
|
@ -134,7 +127,7 @@ impl RibKind<'_> {
|
||||||
| ModuleRibKind(_)
|
| ModuleRibKind(_)
|
||||||
| MacroDefinition(_) => false,
|
| MacroDefinition(_) => false,
|
||||||
AssocItemRibKind
|
AssocItemRibKind
|
||||||
| ItemRibKind
|
| ItemRibKind(_)
|
||||||
| ForwardTyParamBanRibKind
|
| ForwardTyParamBanRibKind
|
||||||
| TyParamAsConstParamTy => true,
|
| TyParamAsConstParamTy => true,
|
||||||
}
|
}
|
||||||
|
@ -406,17 +399,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
|
||||||
visit::walk_poly_trait_ref(self, tref, m);
|
visit::walk_poly_trait_ref(self, tref, m);
|
||||||
}
|
}
|
||||||
fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
|
fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
|
||||||
let generic_params = match foreign_item.kind {
|
match foreign_item.kind {
|
||||||
ForeignItemKind::Fn(_, ref generics) => {
|
ForeignItemKind::Fn(_, ref generics) => {
|
||||||
HasGenericParams(generics, ItemRibKind)
|
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
|
||||||
|
visit::walk_foreign_item(this, foreign_item);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(..) => NoGenericParams,
|
ForeignItemKind::Static(..) => {
|
||||||
ForeignItemKind::Ty => NoGenericParams,
|
self.with_item_rib(HasGenericParams::No, |this| {
|
||||||
ForeignItemKind::Macro(..) => NoGenericParams,
|
visit::walk_foreign_item(this, foreign_item);
|
||||||
};
|
});
|
||||||
self.with_generic_param_rib(generic_params, |this| {
|
}
|
||||||
visit::walk_foreign_item(this, foreign_item);
|
ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {
|
||||||
});
|
visit::walk_foreign_item(self, foreign_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) {
|
fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) {
|
||||||
debug!("(resolving function) entering function");
|
debug!("(resolving function) entering function");
|
||||||
|
@ -660,7 +657,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
|
fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
|
||||||
debug!("resolve_adt");
|
debug!("resolve_adt");
|
||||||
self.with_current_self_item(item, |this| {
|
self.with_current_self_item(item, |this| {
|
||||||
this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
|
this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
|
||||||
let item_def_id = this.r.definitions.local_def_id(item.id);
|
let item_def_id = this.r.definitions.local_def_id(item.id);
|
||||||
this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| {
|
this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| {
|
||||||
visit::walk_item(this, item);
|
visit::walk_item(this, item);
|
||||||
|
@ -719,10 +716,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
ItemKind::TyAlias(_, ref generics) |
|
ItemKind::TyAlias(_, ref generics) |
|
||||||
ItemKind::OpaqueTy(_, ref generics) |
|
ItemKind::OpaqueTy(_, ref generics) |
|
||||||
ItemKind::Fn(_, _, ref generics, _) => {
|
ItemKind::Fn(_, _, ref generics, _) => {
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes),
|
||||||
HasGenericParams(generics, ItemRibKind),
|
|this| visit::walk_item(this, item));
|
||||||
|this| visit::walk_item(this, item)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemKind::Enum(_, ref generics) |
|
ItemKind::Enum(_, ref generics) |
|
||||||
|
@ -740,7 +735,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
|
|
||||||
ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
|
ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
|
||||||
// Create a new rib for the trait-wide type parameters.
|
// Create a new rib for the trait-wide type parameters.
|
||||||
self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
|
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
|
||||||
let local_def_id = this.r.definitions.local_def_id(item.id);
|
let local_def_id = this.r.definitions.local_def_id(item.id);
|
||||||
this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
|
this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
|
@ -748,35 +743,32 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
|
|
||||||
for trait_item in trait_items {
|
for trait_item in trait_items {
|
||||||
this.with_trait_items(trait_items, |this| {
|
this.with_trait_items(trait_items, |this| {
|
||||||
let generic_params = HasGenericParams(
|
this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind,
|
||||||
&trait_item.generics,
|
|this| {
|
||||||
AssocItemRibKind,
|
match trait_item.kind {
|
||||||
);
|
TraitItemKind::Const(ref ty, ref default) => {
|
||||||
this.with_generic_param_rib(generic_params, |this| {
|
this.visit_ty(ty);
|
||||||
match trait_item.kind {
|
|
||||||
TraitItemKind::Const(ref ty, ref default) => {
|
|
||||||
this.visit_ty(ty);
|
|
||||||
|
|
||||||
// Only impose the restrictions of
|
// Only impose the restrictions of
|
||||||
// ConstRibKind for an actual constant
|
// ConstRibKind for an actual constant
|
||||||
// expression in a provided default.
|
// expression in a provided default.
|
||||||
if let Some(ref expr) = *default{
|
if let Some(ref expr) = *default{
|
||||||
this.with_constant_rib(|this| {
|
this.with_constant_rib(|this| {
|
||||||
this.visit_expr(expr);
|
this.visit_expr(expr);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
TraitItemKind::Method(_, _) => {
|
||||||
TraitItemKind::Method(_, _) => {
|
visit::walk_trait_item(this, trait_item)
|
||||||
visit::walk_trait_item(this, trait_item)
|
}
|
||||||
}
|
TraitItemKind::Type(..) => {
|
||||||
TraitItemKind::Type(..) => {
|
visit::walk_trait_item(this, trait_item)
|
||||||
visit::walk_trait_item(this, trait_item)
|
}
|
||||||
}
|
TraitItemKind::Macro(_) => {
|
||||||
TraitItemKind::Macro(_) => {
|
panic!("unexpanded macro in resolve!")
|
||||||
panic!("unexpanded macro in resolve!")
|
}
|
||||||
}
|
};
|
||||||
};
|
});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -785,7 +777,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
|
|
||||||
ItemKind::TraitAlias(ref generics, ref bounds) => {
|
ItemKind::TraitAlias(ref generics, ref bounds) => {
|
||||||
// Create a new rib for the trait-wide type parameters.
|
// Create a new rib for the trait-wide type parameters.
|
||||||
self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
|
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
|
||||||
let local_def_id = this.r.definitions.local_def_id(item.id);
|
let local_def_id = this.r.definitions.local_def_id(item.id);
|
||||||
this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
|
this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| {
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
|
@ -803,7 +795,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
ItemKind::Static(ref ty, _, ref expr) |
|
ItemKind::Static(ref ty, _, ref expr) |
|
||||||
ItemKind::Const(ref ty, ref expr) => {
|
ItemKind::Const(ref ty, ref expr) => {
|
||||||
debug!("resolve_item ItemKind::Const");
|
debug!("resolve_item ItemKind::Const");
|
||||||
self.with_item_rib(|this| {
|
self.with_item_rib(HasGenericParams::No, |this| {
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
this.with_constant_rib(|this| {
|
this.with_constant_rib(|this| {
|
||||||
this.visit_expr(expr);
|
this.visit_expr(expr);
|
||||||
|
@ -824,91 +816,75 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F)
|
fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F)
|
||||||
where F: FnOnce(&mut Self)
|
where F: FnOnce(&mut Self)
|
||||||
{
|
{
|
||||||
debug!("with_generic_param_rib");
|
debug!("with_generic_param_rib");
|
||||||
match generic_params {
|
let mut function_type_rib = Rib::new(kind);
|
||||||
HasGenericParams(generics, rib_kind) => {
|
let mut function_value_rib = Rib::new(kind);
|
||||||
let mut function_type_rib = Rib::new(rib_kind);
|
let mut seen_bindings = FxHashMap::default();
|
||||||
let mut function_value_rib = Rib::new(rib_kind);
|
|
||||||
let mut seen_bindings = FxHashMap::default();
|
|
||||||
// We also can't shadow bindings from the parent item
|
|
||||||
if let AssocItemRibKind = rib_kind {
|
|
||||||
let mut add_bindings_for_ns = |ns| {
|
|
||||||
let parent_rib = self.ribs[ns].iter()
|
|
||||||
.rfind(|rib| if let ItemRibKind = rib.kind { true } else { false })
|
|
||||||
.expect("associated item outside of an item");
|
|
||||||
seen_bindings.extend(
|
|
||||||
parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
add_bindings_for_ns(ValueNS);
|
|
||||||
add_bindings_for_ns(TypeNS);
|
|
||||||
}
|
|
||||||
for param in &generics.params {
|
|
||||||
match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {}
|
|
||||||
GenericParamKind::Type { .. } => {
|
|
||||||
let ident = param.ident.modern();
|
|
||||||
debug!("with_generic_param_rib: {}", param.id);
|
|
||||||
|
|
||||||
if seen_bindings.contains_key(&ident) {
|
// We also can't shadow bindings from the parent item
|
||||||
let span = seen_bindings.get(&ident).unwrap();
|
if let AssocItemRibKind = kind {
|
||||||
let err = ResolutionError::NameAlreadyUsedInParameterList(
|
let mut add_bindings_for_ns = |ns| {
|
||||||
ident.name,
|
let parent_rib = self.ribs[ns].iter()
|
||||||
*span,
|
.rfind(|r| if let ItemRibKind(_) = r.kind { true } else { false })
|
||||||
);
|
.expect("associated item outside of an item");
|
||||||
self.r.report_error(param.ident.span, err);
|
seen_bindings.extend(
|
||||||
}
|
parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)),
|
||||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
);
|
||||||
|
};
|
||||||
|
add_bindings_for_ns(ValueNS);
|
||||||
|
add_bindings_for_ns(TypeNS);
|
||||||
|
}
|
||||||
|
|
||||||
// Plain insert (no renaming).
|
for param in &generics.params {
|
||||||
let res = Res::Def(
|
if let GenericParamKind::Lifetime { .. } = param.kind {
|
||||||
DefKind::TyParam,
|
continue;
|
||||||
self.r.definitions.local_def_id(param.id),
|
|
||||||
);
|
|
||||||
function_type_rib.bindings.insert(ident, res);
|
|
||||||
self.r.record_partial_res(param.id, PartialRes::new(res));
|
|
||||||
}
|
|
||||||
GenericParamKind::Const { .. } => {
|
|
||||||
let ident = param.ident.modern();
|
|
||||||
debug!("with_generic_param_rib: {}", param.id);
|
|
||||||
|
|
||||||
if seen_bindings.contains_key(&ident) {
|
|
||||||
let span = seen_bindings.get(&ident).unwrap();
|
|
||||||
let err = ResolutionError::NameAlreadyUsedInParameterList(
|
|
||||||
ident.name,
|
|
||||||
*span,
|
|
||||||
);
|
|
||||||
self.r.report_error(param.ident.span, err);
|
|
||||||
}
|
|
||||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
|
||||||
|
|
||||||
let res = Res::Def(
|
|
||||||
DefKind::ConstParam,
|
|
||||||
self.r.definitions.local_def_id(param.id),
|
|
||||||
);
|
|
||||||
function_value_rib.bindings.insert(ident, res);
|
|
||||||
self.r.record_partial_res(param.id, PartialRes::new(res));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.ribs[ValueNS].push(function_value_rib);
|
|
||||||
self.ribs[TypeNS].push(function_type_rib);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NoGenericParams => {
|
let def_kind = match param.kind {
|
||||||
// Nothing to do.
|
GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||||
|
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let ident = param.ident.modern();
|
||||||
|
debug!("with_generic_param_rib: {}", param.id);
|
||||||
|
|
||||||
|
if seen_bindings.contains_key(&ident) {
|
||||||
|
let span = seen_bindings.get(&ident).unwrap();
|
||||||
|
let err = ResolutionError::NameAlreadyUsedInParameterList(
|
||||||
|
ident.name,
|
||||||
|
*span,
|
||||||
|
);
|
||||||
|
self.r.report_error(param.ident.span, err);
|
||||||
|
}
|
||||||
|
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||||
|
|
||||||
|
// Plain insert (no renaming).
|
||||||
|
let res = Res::Def(def_kind, self.r.definitions.local_def_id(param.id));
|
||||||
|
|
||||||
|
match param.kind {
|
||||||
|
GenericParamKind::Type { .. } => {
|
||||||
|
function_type_rib.bindings.insert(ident, res);
|
||||||
|
self.r.record_partial_res(param.id, PartialRes::new(res));
|
||||||
|
}
|
||||||
|
GenericParamKind::Const { .. } => {
|
||||||
|
function_value_rib.bindings.insert(ident, res);
|
||||||
|
self.r.record_partial_res(param.id, PartialRes::new(res));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.ribs[ValueNS].push(function_value_rib);
|
||||||
|
self.ribs[TypeNS].push(function_type_rib);
|
||||||
|
|
||||||
f(self);
|
f(self);
|
||||||
|
|
||||||
if let HasGenericParams(..) = generic_params {
|
self.ribs[TypeNS].pop();
|
||||||
self.ribs[TypeNS].pop();
|
self.ribs[ValueNS].pop();
|
||||||
self.ribs[ValueNS].pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
|
fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) {
|
||||||
|
@ -917,8 +893,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
self.label_ribs.pop();
|
self.label_ribs.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) {
|
||||||
self.with_rib(ValueNS, ItemRibKind, |this| this.with_rib(TypeNS, ItemRibKind, f))
|
let kind = ItemRibKind(has_generic_params);
|
||||||
|
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
|
||||||
|
@ -1023,7 +1000,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
impl_items: &[ImplItem]) {
|
impl_items: &[ImplItem]) {
|
||||||
debug!("resolve_implementation");
|
debug!("resolve_implementation");
|
||||||
// If applicable, create a rib for the type parameters.
|
// If applicable, create a rib for the type parameters.
|
||||||
self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| {
|
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
|
||||||
// Dummy self type for better errors if `Self` is used in the trait path.
|
// Dummy self type for better errors if `Self` is used in the trait path.
|
||||||
this.with_self_rib(Res::SelfTy(None, None), |this| {
|
this.with_self_rib(Res::SelfTy(None, None), |this| {
|
||||||
// Resolve the trait reference, if necessary.
|
// Resolve the trait reference, if necessary.
|
||||||
|
@ -1044,9 +1021,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
|
||||||
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
|
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
|
||||||
for impl_item in impl_items {
|
for impl_item in impl_items {
|
||||||
// We also need a new scope for the impl item type parameters.
|
// We also need a new scope for the impl item type parameters.
|
||||||
let generic_params = HasGenericParams(&impl_item.generics,
|
this.with_generic_param_rib(&impl_item.generics,
|
||||||
AssocItemRibKind);
|
AssocItemRibKind,
|
||||||
this.with_generic_param_rib(generic_params, |this| {
|
|this| {
|
||||||
use crate::ResolutionError::*;
|
use crate::ResolutionError::*;
|
||||||
match impl_item.kind {
|
match impl_item.kind {
|
||||||
ImplItemKind::Const(..) => {
|
ImplItemKind::Const(..) => {
|
||||||
|
|
|
@ -61,7 +61,7 @@ use rustc_data_structures::sync::Lrc;
|
||||||
|
|
||||||
use diagnostics::{Suggestion, ImportSuggestion};
|
use diagnostics::{Suggestion, ImportSuggestion};
|
||||||
use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
|
use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
|
||||||
use late::{PathSource, Rib, RibKind::*};
|
use late::{HasGenericParams, PathSource, Rib, RibKind::*};
|
||||||
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
|
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
|
||||||
use macros::{LegacyBinding, LegacyScope};
|
use macros::{LegacyBinding, LegacyScope};
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ impl Ord for BindingError {
|
||||||
|
|
||||||
enum ResolutionError<'a> {
|
enum ResolutionError<'a> {
|
||||||
/// Error E0401: can't use type or const parameters from outer function.
|
/// Error E0401: can't use type or const parameters from outer function.
|
||||||
GenericParamsFromOuterFunction(Res),
|
GenericParamsFromOuterFunction(Res, HasGenericParams),
|
||||||
/// Error E0403: the name is already used for a type or const parameter in this generic
|
/// Error E0403: the name is already used for a type or const parameter in this generic
|
||||||
/// parameter list.
|
/// parameter list.
|
||||||
NameAlreadyUsedInParameterList(Name, Span),
|
NameAlreadyUsedInParameterList(Name, Span),
|
||||||
|
@ -2167,7 +2167,7 @@ impl<'a> Resolver<'a> {
|
||||||
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
|
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
|
||||||
// Nothing to do. Continue.
|
// Nothing to do. Continue.
|
||||||
}
|
}
|
||||||
ItemRibKind | FnItemRibKind | AssocItemRibKind => {
|
ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => {
|
||||||
// This was an attempt to access an upvar inside a
|
// This was an attempt to access an upvar inside a
|
||||||
// named function item. This is not allowed, so we
|
// named function item. This is not allowed, so we
|
||||||
// report an error.
|
// report an error.
|
||||||
|
@ -2195,22 +2195,23 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
|
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
match rib.kind {
|
let has_generic_params = match rib.kind {
|
||||||
NormalRibKind | AssocItemRibKind |
|
NormalRibKind | AssocItemRibKind |
|
||||||
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
|
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
|
||||||
ConstantItemRibKind | TyParamAsConstParamTy => {
|
ConstantItemRibKind | TyParamAsConstParamTy => {
|
||||||
// Nothing to do. Continue.
|
// Nothing to do. Continue.
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
ItemRibKind | FnItemRibKind => {
|
// This was an attempt to use a type parameter outside its scope.
|
||||||
// This was an attempt to use a type parameter outside its scope.
|
ItemRibKind(has_generic_params) => has_generic_params,
|
||||||
if record_used {
|
FnItemRibKind => HasGenericParams::Yes,
|
||||||
self.report_error(
|
};
|
||||||
span, ResolutionError::GenericParamsFromOuterFunction(res)
|
|
||||||
);
|
if record_used {
|
||||||
}
|
self.report_error(span, ResolutionError::GenericParamsFromOuterFunction(
|
||||||
return Res::Err;
|
res, has_generic_params));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Res::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::ConstParam, _) => {
|
Res::Def(DefKind::ConstParam, _) => {
|
||||||
|
@ -2222,15 +2223,18 @@ impl<'a> Resolver<'a> {
|
||||||
ribs.next();
|
ribs.next();
|
||||||
}
|
}
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
if let ItemRibKind | FnItemRibKind = rib.kind {
|
let has_generic_params = match rib.kind {
|
||||||
// This was an attempt to use a const parameter outside its scope.
|
ItemRibKind(has_generic_params) => has_generic_params,
|
||||||
if record_used {
|
FnItemRibKind => HasGenericParams::Yes,
|
||||||
self.report_error(
|
_ => continue,
|
||||||
span, ResolutionError::GenericParamsFromOuterFunction(res)
|
};
|
||||||
);
|
|
||||||
}
|
// This was an attempt to use a const parameter outside its scope.
|
||||||
return Res::Err;
|
if record_used {
|
||||||
|
self.report_error(span, ResolutionError::GenericParamsFromOuterFunction(
|
||||||
|
res, has_generic_params));
|
||||||
}
|
}
|
||||||
|
return Res::Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -2,9 +2,7 @@ error[E0401]: can't use generic parameters from outer function
|
||||||
--> $DIR/inner-static-type-parameter.rs:6:19
|
--> $DIR/inner-static-type-parameter.rs:6:19
|
||||||
|
|
|
|
||||||
LL | fn foo<T>() {
|
LL | fn foo<T>() {
|
||||||
| --- - type parameter from outer function
|
| - type parameter from outer function
|
||||||
| |
|
|
||||||
| try adding a local generic parameter in this method instead
|
|
||||||
LL | static a: Bar<T> = Bar::What;
|
LL | static a: Bar<T> = Bar::What;
|
||||||
| ^ use of generic parameter from outer function
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
unsafe fn foo<A>() {
|
||||||
|
extern "C" {
|
||||||
|
static baz: *const A;
|
||||||
|
//~^ ERROR can't use generic parameters from outer function
|
||||||
|
}
|
||||||
|
|
||||||
|
let bar: *const u64 = core::mem::transmute(&baz);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0401]: can't use generic parameters from outer function
|
||||||
|
--> $DIR/issue-65025-extern-static-parent-generics.rs:3:28
|
||||||
|
|
|
||||||
|
LL | unsafe fn foo<A>() {
|
||||||
|
| - type parameter from outer function
|
||||||
|
LL | extern "C" {
|
||||||
|
LL | static baz: *const A;
|
||||||
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0401`.
|
|
@ -0,0 +1,29 @@
|
||||||
|
#![feature(const_generics)]
|
||||||
|
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
|
||||||
|
fn f<T>() {
|
||||||
|
extern "C" {
|
||||||
|
static a: *const T;
|
||||||
|
//~^ ERROR can't use generic parameters from outer function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g<T: Default>() {
|
||||||
|
static a: *const T = Default::default();
|
||||||
|
//~^ ERROR can't use generic parameters from outer function
|
||||||
|
}
|
||||||
|
|
||||||
|
fn h<const N: usize>() {
|
||||||
|
extern "C" {
|
||||||
|
static a: [u8; N];
|
||||||
|
//~^ ERROR can't use generic parameters from outer function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn i<const N: usize>() {
|
||||||
|
static a: [u8; N] = [0; N];
|
||||||
|
//~^ ERROR can't use generic parameters from outer function
|
||||||
|
//~^^ ERROR can't use generic parameters from outer function
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,53 @@
|
||||||
|
error[E0401]: can't use generic parameters from outer function
|
||||||
|
--> $DIR/issue-65035-static-with-parent-generics.rs:6:26
|
||||||
|
|
|
||||||
|
LL | fn f<T>() {
|
||||||
|
| - type parameter from outer function
|
||||||
|
LL | extern "C" {
|
||||||
|
LL | static a: *const T;
|
||||||
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
error[E0401]: can't use generic parameters from outer function
|
||||||
|
--> $DIR/issue-65035-static-with-parent-generics.rs:12:22
|
||||||
|
|
|
||||||
|
LL | fn g<T: Default>() {
|
||||||
|
| - type parameter from outer function
|
||||||
|
LL | static a: *const T = Default::default();
|
||||||
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
error[E0401]: can't use generic parameters from outer function
|
||||||
|
--> $DIR/issue-65035-static-with-parent-generics.rs:18:24
|
||||||
|
|
|
||||||
|
LL | fn h<const N: usize>() {
|
||||||
|
| - const parameter from outer function
|
||||||
|
LL | extern "C" {
|
||||||
|
LL | static a: [u8; N];
|
||||||
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
error[E0401]: can't use generic parameters from outer function
|
||||||
|
--> $DIR/issue-65035-static-with-parent-generics.rs:24:20
|
||||||
|
|
|
||||||
|
LL | fn i<const N: usize>() {
|
||||||
|
| - const parameter from outer function
|
||||||
|
LL | static a: [u8; N] = [0; N];
|
||||||
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
error[E0401]: can't use generic parameters from outer function
|
||||||
|
--> $DIR/issue-65035-static-with-parent-generics.rs:24:29
|
||||||
|
|
|
||||||
|
LL | fn i<const N: usize>() {
|
||||||
|
| - const parameter from outer function
|
||||||
|
LL | static a: [u8; N] = [0; N];
|
||||||
|
| ^ use of generic parameter from outer function
|
||||||
|
|
||||||
|
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
--> $DIR/issue-65035-static-with-parent-generics.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(const_generics)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0401`.
|
Loading…
Add table
Add a link
Reference in a new issue