-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Account for associated type, const and static when using type argument #62004
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,7 +70,9 @@ use rustc_data_structures::ptr_key::PtrKey; | |
use rustc_data_structures::sync::Lrc; | ||
use smallvec::SmallVec; | ||
|
||
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, CurrentScope, | ||
}; | ||
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; | ||
use macros::{InvocationData, LegacyBinding, ParentScope}; | ||
|
||
|
@@ -210,14 +212,21 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, | |
-> DiagnosticBuilder<'sess> { | ||
match resolution_error { | ||
ResolutionError::GenericParamsFromOuterFunction(outer_res) => { | ||
let msg = resolver.scope.generic_param_resolution_error_message(); | ||
let mut err = struct_span_err!(resolver.session, | ||
span, | ||
E0401, | ||
"can't use generic parameters from outer function", | ||
"can't use generic parameters {}", | ||
msg, | ||
); | ||
err.span_label(span, format!("use of generic parameter from outer function")); | ||
err.span_label(span, &format!("use of generic parameter {}", msg)); | ||
|
||
let cm = resolver.session.source_map(); | ||
let type_param_extra_msg = if resolver.scope.is_other() { | ||
"from outer function " | ||
} else { | ||
"" | ||
}; | ||
match outer_res { | ||
Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => { | ||
if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| { | ||
|
@@ -241,12 +250,18 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, | |
}, | ||
Res::Def(DefKind::TyParam, def_id) => { | ||
if let Some(span) = resolver.definitions.opt_span(def_id) { | ||
err.span_label(span, "type parameter from outer function"); | ||
err.span_label(span, format!( | ||
"type parameter {}being used", | ||
type_param_extra_msg, | ||
)); | ||
} | ||
} | ||
Res::Def(DefKind::ConstParam, def_id) => { | ||
if let Some(span) = resolver.definitions.opt_span(def_id) { | ||
err.span_label(span, "const parameter from outer function"); | ||
err.span_label(span, format!( | ||
"const parameter {}being used", | ||
type_param_extra_msg, | ||
)); | ||
} | ||
} | ||
_ => { | ||
|
@@ -258,7 +273,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, | |
// 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) { | ||
if !resolver.scope.is_other() { | ||
err.help(&format!( | ||
"{} need a type instead of a generic parameter", | ||
resolver.scope.description(), | ||
)); | ||
} else 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, | ||
|
@@ -267,6 +289,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, | |
Applicability::MachineApplicable, | ||
); | ||
} else if let Some(sp) = cm.generate_fn_name_span(span) { | ||
// FIXME: needs to use proper scope navigation to avoid errors like #45447 | ||
err.span_label(sp, | ||
format!("try adding a local generic parameter in this method instead")); | ||
} else { | ||
|
@@ -1688,6 +1711,9 @@ pub struct Resolver<'a> { | |
current_type_ascription: Vec<Span>, | ||
|
||
injected_crate: Option<Module<'a>>, | ||
|
||
/// Used for more accurate error when using type parameters in a associated items. | ||
scope: CurrentScope, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use some other terminology than "scope", it's incredibly overloaded in resolve. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be a better name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
/// Nothing really interesting here; it just provides memory for the rest of the crate. | ||
|
@@ -2013,6 +2039,7 @@ impl<'a> Resolver<'a> { | |
unused_macros: FxHashSet::default(), | ||
current_type_ascription: Vec::new(), | ||
injected_crate: None, | ||
scope: CurrentScope::Other, | ||
} | ||
} | ||
|
||
|
@@ -2520,6 +2547,8 @@ impl<'a> Resolver<'a> { | |
|
||
match item.node { | ||
ItemKind::Ty(_, ref generics) => { | ||
let scope = self.scope; | ||
self.scope = CurrentScope::Type; | ||
self.with_current_self_item(item, |this| { | ||
this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { | ||
let item_def_id = this.definitions.local_def_id(item.id); | ||
|
@@ -2528,6 +2557,7 @@ impl<'a> Resolver<'a> { | |
}) | ||
}) | ||
}); | ||
self.scope = scope; | ||
} | ||
|
||
ItemKind::Existential(_, ref generics) | | ||
|
@@ -2611,13 +2641,20 @@ impl<'a> Resolver<'a> { | |
|
||
ItemKind::Static(ref ty, _, ref expr) | | ||
ItemKind::Const(ref ty, ref expr) => { | ||
let scope = self.scope; | ||
self.scope = match item.node { | ||
ItemKind::Static(..) => CurrentScope::Static, | ||
ItemKind::Const(..) => CurrentScope::Const, | ||
_ => unreachable!(), | ||
}; | ||
debug!("resolve_item ItemKind::Const"); | ||
self.with_item_rib(|this| { | ||
this.visit_ty(ty); | ||
this.with_constant_rib(|this| { | ||
this.visit_expr(expr); | ||
}); | ||
}); | ||
self.scope = scope; | ||
} | ||
|
||
ItemKind::Use(ref use_tree) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
trait Foo { const FOO: Self; } | ||
impl Foo for u32 { const FOO: Self = 1; } | ||
fn bar<T: Foo>(n: T) { | ||
const BASE: T = T::FOO; | ||
//~^ ERROR can't use generic parameters in a `const` | ||
//~| ERROR can't use generic parameters in a `const` | ||
type Type = T; | ||
//~^ ERROR can't use generic parameters in associated type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here |
||
} | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
error[E0401]: can't use generic parameters in a `const` | ||
--> $DIR/issue-45447.rs:4:17 | ||
| | ||
LL | fn bar<T: Foo>(n: T) { | ||
| - type parameter being used | ||
LL | const BASE: T = T::FOO; | ||
| ^ use of generic parameter in a `const` | ||
| | ||
= help: a `const` need a type instead of a generic parameter | ||
|
||
error[E0401]: can't use generic parameters in a `const` | ||
--> $DIR/issue-45447.rs:4:21 | ||
| | ||
LL | fn bar<T: Foo>(n: T) { | ||
| - type parameter being used | ||
LL | const BASE: T = T::FOO; | ||
| ^^^^^^ use of generic parameter in a `const` | ||
| | ||
= help: a `const` need a type instead of a generic parameter | ||
|
||
error[E0401]: can't use generic parameters in associated type | ||
--> $DIR/issue-45447.rs:7:17 | ||
| | ||
LL | fn bar<T: Foo>(n: T) { | ||
| - type parameter being used | ||
... | ||
LL | type Type = T; | ||
| ^ use of generic parameter in associated type | ||
| | ||
= help: associated type need a type instead of a generic parameter | ||
|
||
error: aborting due to 3 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0401`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.