Skip to content

Commit

Permalink
resolve: prohibit foreign statics w/ generics
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
davidtwco committed Oct 8, 2019
1 parent 7870050 commit ccbf2b7
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 181 deletions.
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`.

0 comments on commit ccbf2b7

Please sign in to comment.