Skip to content
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

typeck: prohibit foreign statics w/ generics #65133

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use syntax_pos::{BytePos, Span, MultiSpan};

use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
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};

type Res = def::Res<ast::NodeId>;
Expand Down Expand Up @@ -102,7 +102,7 @@ impl<'a> Resolver<'a> {
&self, span: Span, resolution_error: ResolutionError<'_>
) -> DiagnosticBuilder<'_> {
match resolution_error {
ResolutionError::GenericParamsFromOuterFunction(outer_res) => {
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
let mut err = struct_span_err!(self.session,
span,
E0401,
Expand Down Expand Up @@ -148,22 +148,24 @@ impl<'a> Resolver<'a> {
}
}

// Try to retrieve the span of the function signature and generate a new message
// with a local type or const parameter.
let sugg_msg = &format!("try using a local generic parameter instead");
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
// Suggest the modification to the user
err.span_suggestion(
sugg_span,
sugg_msg,
new_snippet,
Applicability::MachineApplicable,
);
} else if let Some(sp) = cm.generate_fn_name_span(span) {
err.span_label(sp,
format!("try adding a local generic parameter in this method instead"));
} else {
err.help(&format!("try using a local generic parameter instead"));
if has_generic_params == HasGenericParams::Yes {
// Try to retrieve the span of the function signature and generate a new
// message with a local type or const parameter.
let sugg_msg = &format!("try using a local generic parameter instead");
if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) {
// Suggest the modification to the user
err.span_suggestion(
sugg_span,
sugg_msg,
snippet,
Applicability::MachineApplicable,
);
} else if let Some(sp) = cm.generate_fn_name_span(span) {
err.span_label(sp,
format!("try adding a local generic parameter in this method instead"));
} else {
err.help(&format!("try using a local generic parameter instead"));
}
}

err
Expand Down
255 changes: 116 additions & 139 deletions src/librustc_resolve/late.rs

Large diffs are not rendered by default.

46 changes: 25 additions & 21 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use rustc_data_structures::sync::Lrc;

use diagnostics::{Suggestion, ImportSuggestion};
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 macros::{LegacyBinding, LegacyScope};

Expand Down Expand Up @@ -178,7 +178,7 @@ impl Ord for BindingError {

enum ResolutionError<'a> {
/// 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
/// parameter list.
NameAlreadyUsedInParameterList(Name, Span),
Expand Down Expand Up @@ -2167,7 +2167,7 @@ impl<'a> Resolver<'a> {
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
}
ItemRibKind | FnItemRibKind | AssocItemRibKind => {
ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => {
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
Expand Down Expand Up @@ -2195,22 +2195,23 @@ impl<'a> Resolver<'a> {
}
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
for rib in ribs {
match rib.kind {
let has_generic_params = match rib.kind {
NormalRibKind | AssocItemRibKind |
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
ConstantItemRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue.
continue;
}
ItemRibKind | FnItemRibKind => {
// This was an attempt to use a type parameter outside its scope.
if record_used {
self.report_error(
span, ResolutionError::GenericParamsFromOuterFunction(res)
);
}
return Res::Err;
}
// This was an attempt to use a type parameter outside its scope.
ItemRibKind(has_generic_params) => has_generic_params,
FnItemRibKind => HasGenericParams::Yes,
};

if record_used {
self.report_error(span, ResolutionError::GenericParamsFromOuterFunction(
res, has_generic_params));
}
return Res::Err;
}
}
Res::Def(DefKind::ConstParam, _) => {
Expand All @@ -2222,15 +2223,18 @@ impl<'a> Resolver<'a> {
ribs.next();
}
for rib in ribs {
if let ItemRibKind | FnItemRibKind = rib.kind {
// This was an attempt to use a const parameter outside its scope.
if record_used {
self.report_error(
span, ResolutionError::GenericParamsFromOuterFunction(res)
);
}
return Res::Err;
let has_generic_params = match rib.kind {
ItemRibKind(has_generic_params) => has_generic_params,
FnItemRibKind => HasGenericParams::Yes,
_ => continue,
};

// This was an attempt to use a const parameter outside its scope.
if record_used {
self.report_error(span, ResolutionError::GenericParamsFromOuterFunction(
res, has_generic_params));
}
return Res::Err;
}
}
_ => {}
Expand Down
4 changes: 1 addition & 3 deletions src/test/ui/inner-static-type-parameter.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ error[E0401]: can't use generic parameters from outer function
--> $DIR/inner-static-type-parameter.rs:6:19
|
LL | fn foo<T>() {
| --- - type parameter from outer function
| |
| try adding a local generic parameter in this method instead
| - type parameter from outer function
LL | static a: Bar<T> = Bar::What;
| ^ use of generic parameter from outer function

Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs
Original file line number Diff line number Diff line change
@@ -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() { }
Original file line number Diff line number Diff line change
@@ -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`.
29 changes: 29 additions & 0 deletions src/test/ui/resolve/issue-65035-static-with-parent-generics.rs
Original file line number Diff line number Diff line change
@@ -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() {}
53 changes: 53 additions & 0 deletions src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr
Original file line number Diff line number Diff line change
@@ -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`.