mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
rustc_resolve: improve const generic errors
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
This commit is contained in:
@@ -898,7 +898,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
|
||||
}
|
||||
|
||||
// These items live in both the type and value namespaces.
|
||||
ItemKind::Struct(ident, _, ref vdata) => {
|
||||
ItemKind::Struct(ident, ref generics, ref vdata) => {
|
||||
self.build_reduced_graph_for_struct_variant(
|
||||
vdata.fields(),
|
||||
ident,
|
||||
@@ -947,6 +947,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
|
||||
.struct_constructors
|
||||
.insert(local_def_id, (ctor_res, ctor_vis.to_def_id(), ret_fields));
|
||||
}
|
||||
self.r.struct_generics.insert(local_def_id, generics.clone());
|
||||
}
|
||||
|
||||
ItemKind::Union(ident, _, ref vdata) => {
|
||||
|
||||
@@ -883,6 +883,21 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
|
||||
pub applicability: Applicability,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
"you might have meant to introduce a const parameter `{$item_name}` on the {$item_location}",
|
||||
code = "{snippet}",
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub(crate) struct UnexpectedMissingConstParameter {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub snippet: String,
|
||||
pub item_name: String,
|
||||
pub item_location: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
"you might have meant to write a const parameter here",
|
||||
|
||||
@@ -4425,7 +4425,7 @@ fn smart_resolve_path_fragment(
|
||||
let Finalize { node_id, path_span, .. } = finalize;
|
||||
let report_errors = |this: &mut Self, res: Option<Res>| {
|
||||
if this.should_report_errs() {
|
||||
let (err, candidates) = this.smart_resolve_report_errors(
|
||||
let (mut err, candidates) = this.smart_resolve_report_errors(
|
||||
path,
|
||||
None,
|
||||
path_span,
|
||||
@@ -4436,7 +4436,8 @@ fn smart_resolve_path_fragment(
|
||||
|
||||
let def_id = this.parent_scope.module.nearest_parent_mod();
|
||||
let instead = res.is_some();
|
||||
let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
|
||||
let (suggestion, const_err) = if let Some((start, end)) =
|
||||
this.diag_metadata.in_range
|
||||
&& path[0].ident.span.lo() == end.span.lo()
|
||||
&& !matches!(start.kind, ExprKind::Lit(_))
|
||||
{
|
||||
@@ -4448,12 +4449,15 @@ fn smart_resolve_path_fragment(
|
||||
span = span.with_lo(span.lo() + BytePos(1));
|
||||
sugg = "";
|
||||
}
|
||||
Some((
|
||||
span,
|
||||
"you might have meant to write `.` instead of `..`",
|
||||
sugg.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
))
|
||||
(
|
||||
Some((
|
||||
span,
|
||||
"you might have meant to write `.` instead of `..`",
|
||||
sugg.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)),
|
||||
None,
|
||||
)
|
||||
} else if res.is_none()
|
||||
&& let PathSource::Type
|
||||
| PathSource::Expr(_)
|
||||
@@ -4461,9 +4465,14 @@ fn smart_resolve_path_fragment(
|
||||
{
|
||||
this.suggest_adding_generic_parameter(path, source)
|
||||
} else {
|
||||
None
|
||||
(None, None)
|
||||
};
|
||||
|
||||
if let Some(const_err) = const_err {
|
||||
err.cancel();
|
||||
err = const_err;
|
||||
}
|
||||
|
||||
let ue = UseError {
|
||||
err,
|
||||
candidates,
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
|
||||
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
|
||||
use rustc_ast::{
|
||||
self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
|
||||
Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
|
||||
self as ast, AngleBracketedArg, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericArg,
|
||||
GenericArgs, GenericParam, GenericParamKind, Item, ItemKind, MethodCall, NodeId, Path,
|
||||
PathSegment, Ty, TyKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust::{path_to_string, where_bound_predicate_to_string};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize,
|
||||
@@ -37,8 +38,8 @@
|
||||
};
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
use crate::{
|
||||
Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource, Resolver,
|
||||
ScopeSet, Segment, errors, path_names_to_string,
|
||||
Finalize, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource,
|
||||
Resolver, ScopeSet, Segment, errors, path_names_to_string,
|
||||
};
|
||||
|
||||
type Res = def::Res<ast::NodeId>;
|
||||
@@ -3277,11 +3278,203 @@ fn suggest_using_enum_variant(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_adding_generic_parameter(
|
||||
&self,
|
||||
/// Detects missing const parameters in `impl` blocks and suggests adding them.
|
||||
///
|
||||
/// When a const parameter is used in the self type of an `impl` but not declared
|
||||
/// in the `impl`'s own generic parameter list, this function emits a targeted
|
||||
/// diagnostic with a suggestion to add it at the correct position.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```rust,ignore (suggested field is not completely correct, it should be a single suggestion)
|
||||
/// struct C<const A: u8, const X: u8, const P: u32>;
|
||||
///
|
||||
/// impl Foo for C<A, X, P> {}
|
||||
/// // ^ the struct `C` in `C<A, X, P>` is used as the self type
|
||||
/// // ^ ^ ^ but A, X and P are not declared on the impl
|
||||
///
|
||||
/// Suggested fix:
|
||||
///
|
||||
/// impl<const A: u8, const X: u8, const P: u32> Foo for C<A, X, P> {}
|
||||
///
|
||||
/// Current behavior (suggestions are emitted one-by-one):
|
||||
///
|
||||
/// impl<const A: u8> Foo for C<A, X, P> {}
|
||||
/// impl<const X: u8> Foo for C<A, X, P> {}
|
||||
/// impl<const P: u32> Foo for C<A, X, P> {}
|
||||
///
|
||||
/// Ideally the suggestion should aggregate them into a single line:
|
||||
///
|
||||
/// impl<const A: u8, const X: u8, const P: u32> Foo for C<A, X, P> {}
|
||||
/// ```
|
||||
///
|
||||
pub(crate) fn detect_and_suggest_const_parameter_error(
|
||||
&mut self,
|
||||
path: &[Segment],
|
||||
source: PathSource<'_, '_, '_>,
|
||||
) -> Option<(Span, &'static str, String, Applicability)> {
|
||||
source: PathSource<'_, 'ast, 'ra>,
|
||||
) -> Option<Diag<'tcx>> {
|
||||
let Some(item) = self.diag_metadata.current_item else { return None };
|
||||
let ItemKind::Impl(impl_) = &item.kind else { return None };
|
||||
let self_ty = &impl_.self_ty;
|
||||
|
||||
// Represents parameter to the struct whether `A`, `X` or `P`
|
||||
let [current_parameter] = path else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let target_ident = current_parameter.ident;
|
||||
|
||||
// Find the parent segment i.e `C` in `C<A, X, C>`
|
||||
let visitor = ParentPathVisitor::new(self_ty, target_ident);
|
||||
|
||||
let Some(parent_segment) = visitor.parent else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(args) = parent_segment.args.as_ref() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let GenericArgs::AngleBracketed(angle) = args.as_ref() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
// Build map: NodeId of each usage in C<A, X, C> -> its position
|
||||
// e.g NodeId(A) -> 0, NodeId(X) -> 1, NodeId(C) -> 2
|
||||
let usage_to_pos: FxHashMap<NodeId, usize> = angle
|
||||
.args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(pos, arg)| {
|
||||
if let AngleBracketedArg::Arg(GenericArg::Type(ty)) = arg
|
||||
&& let TyKind::Path(_, path) = &ty.kind
|
||||
&& let [segment] = path.segments.as_slice()
|
||||
{
|
||||
Some((segment.id, pos))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Get the position of the missing param in C<A, X, C>
|
||||
// e.g for missing `B` in `C<A, B, C>` this gives idx=1
|
||||
let Some(idx) = current_parameter.id.and_then(|id| usage_to_pos.get(&id).copied()) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
// Now resolve the parent struct `C` to get its definition
|
||||
let ns = source.namespace();
|
||||
let segment = Segment::from(parent_segment);
|
||||
let segments = [segment];
|
||||
let finalize = Finalize::new(parent_segment.id, parent_segment.ident.span);
|
||||
|
||||
if let Ok(Some(resolve)) = self.resolve_qpath_anywhere(
|
||||
&None,
|
||||
&segments,
|
||||
ns,
|
||||
source.defer_to_typeck(),
|
||||
finalize,
|
||||
source,
|
||||
) && let Some(resolve) = resolve.full_res()
|
||||
&& let Res::Def(_, def_id) = resolve
|
||||
&& def_id.is_local()
|
||||
&& let Some(local_def_id) = def_id.as_local()
|
||||
&& let Some(struct_generics) = self.r.struct_generics.get(&local_def_id)
|
||||
&& let target_param = &struct_generics.params[idx]
|
||||
&& let GenericParamKind::Const { ty, .. } = &target_param.kind
|
||||
&& let TyKind::Path(_, path) = &ty.kind
|
||||
{
|
||||
let full_type = path
|
||||
.segments
|
||||
.iter()
|
||||
.map(|seg| seg.ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("::");
|
||||
|
||||
// Find the first impl param whose position in C<A, X, C>
|
||||
// is strictly greater than our missing param's index
|
||||
// e.g missing B(idx=1), impl has A(pos=0) and C(pos=2)
|
||||
// C has pos=2 > 1 so insert before C
|
||||
let next_impl_param = impl_.generics.params.iter().find(|impl_param| {
|
||||
angle
|
||||
.args
|
||||
.iter()
|
||||
.find_map(|arg| {
|
||||
if let AngleBracketedArg::Arg(GenericArg::Type(ty)) = arg
|
||||
&& let TyKind::Path(_, path) = &ty.kind
|
||||
&& let [segment] = path.segments.as_slice()
|
||||
&& segment.ident == impl_param.ident
|
||||
{
|
||||
usage_to_pos.get(&segment.id).copied()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map_or(false, |pos| pos > idx)
|
||||
});
|
||||
|
||||
let (insert_span, snippet) = match next_impl_param {
|
||||
Some(next_param) => {
|
||||
// Insert in the middle before next_param
|
||||
// e.g impl<A, C> -> impl<A, const B: u8, C>
|
||||
(
|
||||
next_param.span().shrink_to_lo(),
|
||||
format!("const {}: {}, ", target_ident, full_type),
|
||||
)
|
||||
}
|
||||
None => match impl_.generics.params.last() {
|
||||
Some(last) => {
|
||||
// Append after last existing param
|
||||
// e.g impl<A, B> -> impl<A, B, const C: u8>
|
||||
(
|
||||
last.span().shrink_to_hi(),
|
||||
format!(", const {}: {}", target_ident, full_type),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
// No generics at all on impl
|
||||
// e.g impl Foo for C<A> -> impl<const A: u8> Foo for C<A>
|
||||
(
|
||||
impl_.generics.span.shrink_to_hi(),
|
||||
format!("<const {}: {}>", target_ident, full_type),
|
||||
)
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut err = self.r.dcx().struct_span_err(
|
||||
target_ident.span,
|
||||
format!("cannot find const `{}` in this scope", target_ident),
|
||||
);
|
||||
|
||||
err.code(E0425);
|
||||
|
||||
err.span_label(target_ident.span, "not found in this scope");
|
||||
|
||||
err.span_label(
|
||||
target_param.span(),
|
||||
format!("corresponding const parameter on the type defined here",),
|
||||
);
|
||||
|
||||
err.subdiagnostic(errors::UnexpectedMissingConstParameter {
|
||||
span: insert_span,
|
||||
snippet,
|
||||
item_name: format!("{}", target_ident),
|
||||
item_location: String::from("impl"),
|
||||
});
|
||||
|
||||
return Some(err);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn suggest_adding_generic_parameter(
|
||||
&mut self,
|
||||
path: &[Segment],
|
||||
source: PathSource<'_, 'ast, 'ra>,
|
||||
) -> (Option<(Span, &'static str, String, Applicability)>, Option<Diag<'tcx>>) {
|
||||
let (ident, span) = match path {
|
||||
[segment]
|
||||
if !segment.has_generic_args
|
||||
@@ -3290,13 +3483,13 @@ pub(crate) fn suggest_adding_generic_parameter(
|
||||
{
|
||||
(segment.ident.to_string(), segment.ident.span)
|
||||
}
|
||||
_ => return None,
|
||||
_ => return (None, None),
|
||||
};
|
||||
let mut iter = ident.chars().map(|c| c.is_uppercase());
|
||||
let single_uppercase_char =
|
||||
matches!(iter.next(), Some(true)) && matches!(iter.next(), None);
|
||||
if !self.diag_metadata.currently_processing_generic_args && !single_uppercase_char {
|
||||
return None;
|
||||
return (None, None);
|
||||
}
|
||||
match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) {
|
||||
(Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
|
||||
@@ -3326,18 +3519,21 @@ pub(crate) fn suggest_adding_generic_parameter(
|
||||
// | ^- help: you might be missing a type parameter: `, A`
|
||||
// | |
|
||||
// | not found in this scope
|
||||
return None;
|
||||
return (None, None);
|
||||
}
|
||||
|
||||
let (msg, sugg) = match source {
|
||||
PathSource::Type | PathSource::PreciseCapturingArg(TypeNS) => {
|
||||
if let Some(err) = self.detect_and_suggest_const_parameter_error(path, source) {
|
||||
return (None, Some(err));
|
||||
}
|
||||
("you might be missing a type parameter", ident)
|
||||
}
|
||||
PathSource::Expr(_) | PathSource::PreciseCapturingArg(ValueNS) => (
|
||||
"you might be missing a const parameter",
|
||||
format!("const {ident}: /* Type */"),
|
||||
),
|
||||
_ => return None,
|
||||
_ => return (None, None),
|
||||
};
|
||||
let (span, sugg) = if let [.., param] = &generics.params[..] {
|
||||
let span = if let [.., bound] = ¶m.bounds[..] {
|
||||
@@ -3355,18 +3551,18 @@ pub(crate) fn suggest_adding_generic_parameter(
|
||||
};
|
||||
// Do not suggest if this is coming from macro expansion.
|
||||
if span.can_be_used_for_suggestions() {
|
||||
return Some((
|
||||
return (Some((
|
||||
span.shrink_to_hi(),
|
||||
msg,
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
));
|
||||
)), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
None
|
||||
(None, None)
|
||||
}
|
||||
|
||||
/// Given the target `label`, search the `rib_index`th label rib for similarly named labels,
|
||||
@@ -4349,3 +4545,44 @@ pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident
|
||||
.with_span_label(shadower, format!("label `{name}` already in scope"))
|
||||
.emit();
|
||||
}
|
||||
|
||||
struct ParentPathVisitor<'a> {
|
||||
target: Ident,
|
||||
parent: Option<&'a PathSegment>,
|
||||
stack: Vec<&'a Ty>,
|
||||
}
|
||||
|
||||
impl<'a> ParentPathVisitor<'a> {
|
||||
fn new(self_ty: &'a Ty, target: Ident) -> Self {
|
||||
let mut v = ParentPathVisitor { target, parent: None, stack: Vec::new() };
|
||||
|
||||
v.visit_ty(self_ty);
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor<'a> for ParentPathVisitor<'a> {
|
||||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
if self.parent.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
// push current type
|
||||
self.stack.push(ty);
|
||||
|
||||
if let TyKind::Path(_, path) = &ty.kind
|
||||
// is this just `N`?
|
||||
&& let [segment] = path.segments.as_slice()
|
||||
&& segment.ident == self.target
|
||||
// parent is previous element in stack
|
||||
&& let [.., parent_ty, _ty] = self.stack.as_slice()
|
||||
&& let TyKind::Path(_, parent_path) = &parent_ty.kind
|
||||
{
|
||||
self.parent = parent_path.segments.first();
|
||||
}
|
||||
|
||||
walk_ty(self, ty);
|
||||
|
||||
self.stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::{
|
||||
self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs,
|
||||
NodeId, Path, attr,
|
||||
Generics, NodeId, Path, attr,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default};
|
||||
use rustc_data_structures::intern::Interned;
|
||||
@@ -1317,6 +1317,10 @@ pub struct Resolver<'ra, 'tcx> {
|
||||
/// Also includes of list of each fields visibility
|
||||
struct_constructors: LocalDefIdMap<(Res, Visibility<DefId>, Vec<Visibility<DefId>>)> = Default::default(),
|
||||
|
||||
/// for all the struct
|
||||
/// it's not used during normal resolution, only for better error reporting.
|
||||
struct_generics: LocalDefIdMap<Generics> = Default::default(),
|
||||
|
||||
lint_buffer: LintBuffer,
|
||||
|
||||
next_node_id: NodeId = CRATE_NODE_ID,
|
||||
|
||||
@@ -14,7 +14,7 @@ const fn baz() -> i32 {
|
||||
|
||||
fn main() {
|
||||
foo::<baz()>(); //~ ERROR expected type, found function `baz`
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
//~^ ERROR unresolved item provided when a constant was expected
|
||||
foo::<bar(bar(1, 1), bar(1, 1))>(); //~ ERROR expected type, found `1`
|
||||
foo::<bar(1, 1)>(); //~ ERROR expected type, found `1`
|
||||
foo::<bar(FOO, 2)>(); //~ ERROR expected type, found `2`
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#![crate_type="lib"]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
struct A<const N: u8>;
|
||||
trait Foo {}
|
||||
impl Foo for A<N> {}
|
||||
//~^ ERROR cannot find type
|
||||
//~| ERROR unresolved item provided when a constant
|
||||
//~^ ERROR cannot find const `N` in this scope
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
|
||||
struct B<const N: u8>;
|
||||
impl<N> Foo for B<N> {}
|
||||
@@ -12,5 +12,16 @@ impl<N> Foo for B<N> {}
|
||||
|
||||
struct C<const C: u8, const N: u8>;
|
||||
impl<const N: u8> Foo for C<N, T> {}
|
||||
//~^ ERROR cannot find type
|
||||
//~| ERROR unresolved item provided when a constant
|
||||
//~^ ERROR cannot find const `T` in this scope
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
|
||||
struct D<const E: u8, const X: u8, const P: u32>;
|
||||
impl Foo for D<E, X, P> {}
|
||||
//~^ ERROR cannot find const `E` in this scope
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
//~| ERROR cannot find const `X` in this scope
|
||||
//~| ERROR cannot find const `P` in this scope
|
||||
struct R<const O: u8, const G: u8, const F: u32>;
|
||||
impl<const F: u8, const H: u32> Foo for D<F, Q, D> {}
|
||||
//~^ ERROR cannot find const `Q` in this scope
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
|
||||
@@ -1,40 +1,82 @@
|
||||
error[E0425]: cannot find type `N` in this scope
|
||||
error[E0425]: cannot find const `N` in this scope
|
||||
--> $DIR/invalid-const-arguments.rs:5:16
|
||||
|
|
||||
LL | struct A<const N: u8>;
|
||||
| ---------------------- similarly named struct `A` defined here
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
LL | trait Foo {}
|
||||
LL | impl Foo for A<N> {}
|
||||
| ^
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: a struct with a similar name exists
|
||||
help: you might have meant to introduce a const parameter `N` on the impl
|
||||
|
|
||||
LL - impl Foo for A<N> {}
|
||||
LL + impl Foo for A<A> {}
|
||||
|
|
||||
help: you might be missing a type parameter
|
||||
|
|
||||
LL | impl<N> Foo for A<N> {}
|
||||
| +++
|
||||
LL | impl<const N: u8> Foo for A<N> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0425]: cannot find type `T` in this scope
|
||||
error[E0425]: cannot find const `T` in this scope
|
||||
--> $DIR/invalid-const-arguments.rs:14:32
|
||||
|
|
||||
LL | struct A<const N: u8>;
|
||||
| ---------------------- similarly named struct `A` defined here
|
||||
...
|
||||
LL | struct C<const C: u8, const N: u8>;
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
LL | impl<const N: u8> Foo for C<N, T> {}
|
||||
| ^
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: a struct with a similar name exists
|
||||
help: you might have meant to introduce a const parameter `T` on the impl
|
||||
|
|
||||
LL - impl<const N: u8> Foo for C<N, T> {}
|
||||
LL + impl<const N: u8> Foo for C<N, A> {}
|
||||
LL | impl<const N: u8, const T: u8> Foo for C<N, T> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0425]: cannot find const `E` in this scope
|
||||
--> $DIR/invalid-const-arguments.rs:19:16
|
||||
|
|
||||
help: you might be missing a type parameter
|
||||
LL | struct D<const E: u8, const X: u8, const P: u32>;
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
LL | impl Foo for D<E, X, P> {}
|
||||
| ^ not found in this scope
|
||||
|
|
||||
LL | impl<const N: u8, T> Foo for C<N, T> {}
|
||||
| +++
|
||||
help: you might have meant to introduce a const parameter `E` on the impl
|
||||
|
|
||||
LL | impl<const E: u8> Foo for D<E, X, P> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0425]: cannot find const `X` in this scope
|
||||
--> $DIR/invalid-const-arguments.rs:19:19
|
||||
|
|
||||
LL | struct D<const E: u8, const X: u8, const P: u32>;
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
LL | impl Foo for D<E, X, P> {}
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: you might have meant to introduce a const parameter `X` on the impl
|
||||
|
|
||||
LL | impl<const X: u8> Foo for D<E, X, P> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0425]: cannot find const `P` in this scope
|
||||
--> $DIR/invalid-const-arguments.rs:19:22
|
||||
|
|
||||
LL | struct D<const E: u8, const X: u8, const P: u32>;
|
||||
| ------------ corresponding const parameter on the type defined here
|
||||
LL | impl Foo for D<E, X, P> {}
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: you might have meant to introduce a const parameter `P` on the impl
|
||||
|
|
||||
LL | impl<const P: u32> Foo for D<E, X, P> {}
|
||||
| ++++++++++++++
|
||||
|
||||
error[E0425]: cannot find const `Q` in this scope
|
||||
--> $DIR/invalid-const-arguments.rs:25:46
|
||||
|
|
||||
LL | struct D<const E: u8, const X: u8, const P: u32>;
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
...
|
||||
LL | impl<const F: u8, const H: u32> Foo for D<F, Q, D> {}
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: you might have meant to introduce a const parameter `Q` on the impl
|
||||
|
|
||||
LL | impl<const F: u8, const H: u32, const Q: u8> Foo for D<F, Q, D> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-const-arguments.rs:5:16
|
||||
@@ -70,7 +112,29 @@ help: if this generic argument was intended as a const parameter, surround it wi
|
||||
LL | impl<const N: u8> Foo for C<N, { T }> {}
|
||||
| + +
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-const-arguments.rs:19:16
|
||||
|
|
||||
LL | impl Foo for D<E, X, P> {}
|
||||
| ^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | impl Foo for D<{ E }, X, P> {}
|
||||
| + +
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-const-arguments.rs:25:46
|
||||
|
|
||||
LL | impl<const F: u8, const H: u32> Foo for D<F, Q, D> {}
|
||||
| ^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | impl<const F: u8, const H: u32> Foo for D<F, { Q }, D> {}
|
||||
| + +
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0425, E0747.
|
||||
For more information about an error, try `rustc --explain E0425`.
|
||||
|
||||
@@ -12,27 +12,27 @@ enum CompileFlag {
|
||||
|
||||
pub fn test_1<const CF: CompileFlag>() {}
|
||||
pub fn test_2<T, const CF: CompileFlag>(x: T) {}
|
||||
pub struct Example<const CF: CompileFlag, T=u32>{
|
||||
pub struct Example<const CF: CompileFlag, T = u32> {
|
||||
x: T,
|
||||
}
|
||||
|
||||
impl<const CF: CompileFlag, T> Example<CF, T> {
|
||||
const ASSOC_FLAG: CompileFlag = CompileFlag::A;
|
||||
const ASSOC_FLAG: CompileFlag = CompileFlag::A;
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
test_1::<CompileFlag::A>();
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
test_1::<CompileFlag::A>();
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
|
||||
test_2::<_, CompileFlag::A>(0);
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
test_2::<_, CompileFlag::A>(0);
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
|
||||
let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
//~^ ERROR: expected type, found variant
|
||||
//~| ERROR: unresolved item provided when a constant was expected
|
||||
|
||||
let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
|
||||
//~^ ERROR: type provided when a constant was expected
|
||||
let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
|
||||
//~^ ERROR: type provided when a constant was expected
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
error[E0573]: expected type, found variant `CompileFlag::A`
|
||||
--> $DIR/invalid-enum.rs:24:12
|
||||
--> $DIR/invalid-enum.rs:24:14
|
||||
|
|
||||
LL | test_1::<CompileFlag::A>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
LL | test_1::<CompileFlag::A>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
|
||||
error[E0573]: expected type, found variant `CompileFlag::A`
|
||||
--> $DIR/invalid-enum.rs:28:15
|
||||
--> $DIR/invalid-enum.rs:28:17
|
||||
|
|
||||
LL | test_2::<_, CompileFlag::A>(0);
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
LL | test_2::<_, CompileFlag::A>(0);
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
|
||||
error[E0573]: expected type, found variant `CompileFlag::A`
|
||||
--> $DIR/invalid-enum.rs:32:18
|
||||
--> $DIR/invalid-enum.rs:32:20
|
||||
|
|
||||
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^
|
||||
| |
|
||||
| not a type
|
||||
| help: try using the variant's enum: `CompileFlag`
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:24:12
|
||||
--> $DIR/invalid-enum.rs:24:14
|
||||
|
|
||||
LL | test_1::<CompileFlag::A>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | test_1::<CompileFlag::A>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | test_1::<{ CompileFlag::A }>();
|
||||
| + +
|
||||
LL | test_1::<{ CompileFlag::A }>();
|
||||
| + +
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:28:15
|
||||
--> $DIR/invalid-enum.rs:28:17
|
||||
|
|
||||
LL | test_2::<_, CompileFlag::A>(0);
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | test_2::<_, CompileFlag::A>(0);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | test_2::<_, { CompileFlag::A }>(0);
|
||||
| + +
|
||||
LL | test_2::<_, { CompileFlag::A }>(0);
|
||||
| + +
|
||||
|
||||
error[E0747]: unresolved item provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:32:18
|
||||
--> $DIR/invalid-enum.rs:32:20
|
||||
|
|
||||
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
|
||||
| + +
|
||||
LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
|
||||
| + +
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/invalid-enum.rs:36:18
|
||||
--> $DIR/invalid-enum.rs:36:20
|
||||
|
|
||||
LL | let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
LL | let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: if this generic argument was intended as a const parameter, surround it with braces
|
||||
|
|
||||
LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
|
||||
| + +
|
||||
LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
|
||||
| + +
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
struct X<const N: u8>();
|
||||
|
||||
impl X<N> {}
|
||||
//~^ ERROR cannot find type `N` in this scope
|
||||
//~^ ERROR cannot find const `N` in this scope
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
impl<T, const A: u8 = 2> X<N> {}
|
||||
//~^ ERROR cannot find type `N` in this scope
|
||||
//~^ ERROR cannot find const `N` in this scope
|
||||
//~| ERROR defaults for generic parameters are not allowed here
|
||||
//~| ERROR unresolved item provided when a constant was expected
|
||||
|
||||
@@ -15,5 +15,4 @@ fn foo(_: T) where T: Send {}
|
||||
fn bar<const N: u8>(_: A) {}
|
||||
//~^ ERROR cannot find type `A` in this scope
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
||||
@@ -1,39 +1,30 @@
|
||||
error[E0425]: cannot find type `N` in this scope
|
||||
error[E0425]: cannot find const `N` in this scope
|
||||
--> $DIR/missing-type-parameter2.rs:3:8
|
||||
|
|
||||
LL | struct X<const N: u8>();
|
||||
| ------------------------ similarly named struct `X` defined here
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
LL |
|
||||
LL | impl X<N> {}
|
||||
| ^
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: a struct with a similar name exists
|
||||
help: you might have meant to introduce a const parameter `N` on the impl
|
||||
|
|
||||
LL - impl X<N> {}
|
||||
LL + impl X<X> {}
|
||||
|
|
||||
help: you might be missing a type parameter
|
||||
|
|
||||
LL | impl<N> X<N> {}
|
||||
| +++
|
||||
LL | impl<const N: u8> X<N> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0425]: cannot find type `N` in this scope
|
||||
error[E0425]: cannot find const `N` in this scope
|
||||
--> $DIR/missing-type-parameter2.rs:6:28
|
||||
|
|
||||
LL | struct X<const N: u8>();
|
||||
| ----------- corresponding const parameter on the type defined here
|
||||
...
|
||||
LL | impl<T, const A: u8 = 2> X<N> {}
|
||||
| - ^
|
||||
| |
|
||||
| similarly named type parameter `T` defined here
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: a type parameter with a similar name exists
|
||||
help: you might have meant to introduce a const parameter `N` on the impl
|
||||
|
|
||||
LL - impl<T, const A: u8 = 2> X<N> {}
|
||||
LL + impl<T, const A: u8 = 2> X<T> {}
|
||||
|
|
||||
help: you might be missing a type parameter
|
||||
|
|
||||
LL | impl<T, const A: u8 = 2, N> X<N> {}
|
||||
| +++
|
||||
LL | impl<T, const A: u8 = 2, const N: u8> X<N> {}
|
||||
| +++++++++++++
|
||||
|
||||
error[E0425]: cannot find type `T` in this scope
|
||||
--> $DIR/missing-type-parameter2.rs:11:20
|
||||
|
||||
Reference in New Issue
Block a user