Skip to content

Commit 6bb93ca

Browse files
committed
Const generic parameters aren't bounds, even if we end up erroring because of the bound that binds the parameter's type
1 parent 1cb75dc commit 6bb93ca

19 files changed

+144
-126
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+101-83
Original file line numberDiff line numberDiff line change
@@ -2776,97 +2776,115 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27762776
let mut this = "this bound";
27772777
let mut note = None;
27782778
let mut help = None;
2779-
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder()
2780-
&& let ty::ClauseKind::Trait(trait_pred) = clause
2781-
{
2782-
let def_id = trait_pred.def_id();
2783-
let visible_item = if let Some(local) = def_id.as_local() {
2784-
// Check for local traits being reachable.
2785-
let vis = &tcx.resolutions(()).effective_visibilities;
2786-
// Account for non-`pub` traits in the root of the local crate.
2787-
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
2788-
vis.is_reachable(local) || is_locally_reachable
2789-
} else {
2790-
// Check for foreign traits being reachable.
2791-
tcx.visible_parent_map(()).get(&def_id).is_some()
2792-
};
2793-
if tcx.is_lang_item(def_id, LangItem::Sized) {
2794-
// Check if this is an implicit bound, even in foreign crates.
2795-
if tcx
2796-
.generics_of(item_def_id)
2797-
.own_params
2798-
.iter()
2799-
.any(|param| tcx.def_span(param.def_id) == span)
2800-
{
2801-
a = "an implicit `Sized`";
2802-
this = "the implicit `Sized` requirement on this type parameter";
2803-
}
2804-
if let Some(hir::Node::TraitItem(hir::TraitItem {
2805-
generics,
2806-
kind: hir::TraitItemKind::Type(bounds, None),
2807-
..
2808-
})) = tcx.hir().get_if_local(item_def_id)
2809-
// Do not suggest relaxing if there is an explicit `Sized` obligation.
2810-
&& !bounds.iter()
2811-
.filter_map(|bound| bound.trait_ref())
2812-
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
2813-
{
2814-
let (span, separator) = if let [.., last] = bounds {
2815-
(last.span().shrink_to_hi(), " +")
2779+
if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() {
2780+
match clause {
2781+
ty::ClauseKind::Trait(trait_pred) => {
2782+
let def_id = trait_pred.def_id();
2783+
let visible_item = if let Some(local) = def_id.as_local() {
2784+
// Check for local traits being reachable.
2785+
let vis = &tcx.resolutions(()).effective_visibilities;
2786+
// Account for non-`pub` traits in the root of the local crate.
2787+
let is_locally_reachable = tcx.parent(def_id).is_crate_root();
2788+
vis.is_reachable(local) || is_locally_reachable
28162789
} else {
2817-
(generics.span.shrink_to_hi(), ":")
2790+
// Check for foreign traits being reachable.
2791+
tcx.visible_parent_map(()).get(&def_id).is_some()
28182792
};
2819-
err.span_suggestion_verbose(
2820-
span,
2821-
"consider relaxing the implicit `Sized` restriction",
2822-
format!("{separator} ?Sized"),
2823-
Applicability::MachineApplicable,
2824-
);
2825-
}
2826-
}
2827-
if let DefKind::Trait = tcx.def_kind(item_def_id)
2828-
&& !visible_item
2829-
{
2830-
note = Some(format!(
2831-
"`{short_item_name}` is a \"sealed trait\", because to implement it \
2793+
if tcx.is_lang_item(def_id, LangItem::Sized) {
2794+
// Check if this is an implicit bound, even in foreign crates.
2795+
if tcx
2796+
.generics_of(item_def_id)
2797+
.own_params
2798+
.iter()
2799+
.any(|param| tcx.def_span(param.def_id) == span)
2800+
{
2801+
a = "an implicit `Sized`";
2802+
this =
2803+
"the implicit `Sized` requirement on this type parameter";
2804+
}
2805+
if let Some(hir::Node::TraitItem(hir::TraitItem {
2806+
generics,
2807+
kind: hir::TraitItemKind::Type(bounds, None),
2808+
..
2809+
})) = tcx.hir().get_if_local(item_def_id)
2810+
// Do not suggest relaxing if there is an explicit `Sized` obligation.
2811+
&& !bounds.iter()
2812+
.filter_map(|bound| bound.trait_ref())
2813+
.any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait())
2814+
{
2815+
let (span, separator) = if let [.., last] = bounds {
2816+
(last.span().shrink_to_hi(), " +")
2817+
} else {
2818+
(generics.span.shrink_to_hi(), ":")
2819+
};
2820+
err.span_suggestion_verbose(
2821+
span,
2822+
"consider relaxing the implicit `Sized` restriction",
2823+
format!("{separator} ?Sized"),
2824+
Applicability::MachineApplicable,
2825+
);
2826+
}
2827+
}
2828+
if let DefKind::Trait = tcx.def_kind(item_def_id)
2829+
&& !visible_item
2830+
{
2831+
note = Some(format!(
2832+
"`{short_item_name}` is a \"sealed trait\", because to implement it \
28322833
you also need to implement `{}`, which is not accessible; this is \
28332834
usually done to force you to use one of the provided types that \
28342835
already implement it",
2835-
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
2836-
));
2837-
let impls_of = tcx.trait_impls_of(def_id);
2838-
let impls = impls_of
2839-
.non_blanket_impls()
2840-
.values()
2841-
.flatten()
2842-
.chain(impls_of.blanket_impls().iter())
2843-
.collect::<Vec<_>>();
2844-
if !impls.is_empty() {
2845-
let len = impls.len();
2846-
let mut types = impls
2847-
.iter()
2848-
.map(|t| {
2849-
with_no_trimmed_paths!(format!(
2850-
" {}",
2851-
tcx.type_of(*t).instantiate_identity(),
2852-
))
2853-
})
2854-
.collect::<Vec<_>>();
2855-
let post = if types.len() > 9 {
2856-
types.truncate(8);
2857-
format!("\nand {} others", len - 8)
2836+
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
2837+
));
2838+
let impls_of = tcx.trait_impls_of(def_id);
2839+
let impls = impls_of
2840+
.non_blanket_impls()
2841+
.values()
2842+
.flatten()
2843+
.chain(impls_of.blanket_impls().iter())
2844+
.collect::<Vec<_>>();
2845+
if !impls.is_empty() {
2846+
let len = impls.len();
2847+
let mut types = impls
2848+
.iter()
2849+
.map(|t| {
2850+
with_no_trimmed_paths!(format!(
2851+
" {}",
2852+
tcx.type_of(*t).instantiate_identity(),
2853+
))
2854+
})
2855+
.collect::<Vec<_>>();
2856+
let post = if types.len() > 9 {
2857+
types.truncate(8);
2858+
format!("\nand {} others", len - 8)
2859+
} else {
2860+
String::new()
2861+
};
2862+
help = Some(format!(
2863+
"the following type{} implement{} the trait:\n{}{post}",
2864+
pluralize!(len),
2865+
if len == 1 { "s" } else { "" },
2866+
types.join("\n"),
2867+
));
2868+
}
2869+
}
2870+
}
2871+
ty::ClauseKind::ConstArgHasType(..) => {
2872+
let descr =
2873+
format!("required by a const generic parameter in `{item_name}`");
2874+
if span.is_visible(sm) {
2875+
let msg = format!(
2876+
"required by this const generic parameter in `{short_item_name}`"
2877+
);
2878+
multispan.push_span_label(span, msg);
2879+
err.span_note(multispan, descr);
28582880
} else {
2859-
String::new()
2860-
};
2861-
help = Some(format!(
2862-
"the following type{} implement{} the trait:\n{}{post}",
2863-
pluralize!(len),
2864-
if len == 1 { "s" } else { "" },
2865-
types.join("\n"),
2866-
));
2881+
err.span_note(tcx.def_span(item_def_id), descr);
2882+
}
2883+
return;
28672884
}
2885+
_ => (),
28682886
}
2869-
};
2887+
}
28702888
let descr = format!("required by {a} bound in `{item_name}`");
28712889
if span.is_visible(sm) {
28722890
let msg = format!("required by {this} in `{short_item_name}`");

tests/ui/const-generics/defaults/doesnt_infer.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0284]: type annotations needed for `Foo<_>`
44
LL | let foo = Foo::foo();
55
| ^^^ ---------- type must be known at this point
66
|
7-
note: required by a bound in `Foo::<N>::foo`
7+
note: required by a const generic parameter in `Foo::<N>::foo`
88
--> $DIR/doesnt_infer.rs:5:6
99
|
1010
LL | impl<const N: u32> Foo<N> {
11-
| ^^^^^^^^^^^^ required by this bound in `Foo::<N>::foo`
11+
| ^^^^^^^^^^^^ required by this const generic parameter in `Foo::<N>::foo`
1212
LL | fn foo() -> Self {
1313
| --- required by a bound in this associated function
1414
help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified
@@ -22,11 +22,11 @@ error[E0284]: type annotations needed for `Foo<_>`
2222
LL | let foo = Foo::foo();
2323
| ^^^ --- type must be known at this point
2424
|
25-
note: required by a bound in `Foo`
25+
note: required by a const generic parameter in `Foo`
2626
--> $DIR/doesnt_infer.rs:3:12
2727
|
2828
LL | struct Foo<const N: u32 = 2>;
29-
| ^^^^^^^^^^^^^^^^ required by this bound in `Foo`
29+
| ^^^^^^^^^^^^^^^^ required by this const generic parameter in `Foo`
3030
help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified
3131
|
3232
LL | let foo: Foo<N> = Foo::foo();

tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ error[E0284]: type annotations needed
3737
LL | uwu();
3838
| ^^^ cannot infer the value of the const parameter `N` declared on the function `uwu`
3939
|
40-
note: required by a bound in `uwu`
40+
note: required by a const generic parameter in `uwu`
4141
--> $DIR/rp_impl_trait_fail.rs:16:8
4242
|
4343
LL | fn uwu<const N: u8>() -> impl Traitor<N> {
44-
| ^^^^^^^^^^^ required by this bound in `uwu`
44+
| ^^^^^^^^^^^ required by this const generic parameter in `uwu`
4545
help: consider specifying the generic argument
4646
|
4747
LL | uwu::<N>();

tests/ui/const-generics/generic_arg_infer/issue-91614.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0284]: type annotations needed for `Mask<_, _>`
44
LL | let y = Mask::<_, _>::splat(false);
55
| ^ -------------------------- type must be known at this point
66
|
7-
note: required by a bound in `Mask::<T, N>::splat`
7+
note: required by a const generic parameter in `Mask::<T, N>::splat`
88
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
99
help: consider giving `y` an explicit type, where the value of const parameter `N` is specified
1010
|
@@ -17,7 +17,7 @@ error[E0284]: type annotations needed for `Mask<_, _>`
1717
LL | let y = Mask::<_, _>::splat(false);
1818
| ^ ------------ type must be known at this point
1919
|
20-
note: required by a bound in `Mask`
20+
note: required by a const generic parameter in `Mask`
2121
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
2222
help: consider giving `y` an explicit type, where the value of const parameter `N` is specified
2323
|

tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ error[E0284]: type annotations needed for `ArrayHolder<_>`
2424
LL | let mut array = ArrayHolder::new();
2525
| ^^^^^^^^^ ------------------ type must be known at this point
2626
|
27-
note: required by a bound in `ArrayHolder::<X>::new`
27+
note: required by a const generic parameter in `ArrayHolder::<X>::new`
2828
--> $DIR/issue-62504.rs:16:6
2929
|
3030
LL | impl<const X: usize> ArrayHolder<X> {
31-
| ^^^^^^^^^^^^^^ required by this bound in `ArrayHolder::<X>::new`
31+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `ArrayHolder::<X>::new`
3232
LL | pub const fn new() -> Self {
3333
| --- required by a bound in this associated function
3434
help: consider giving `array` an explicit type, where the value of const parameter `X` is specified
@@ -42,11 +42,11 @@ error[E0284]: type annotations needed for `ArrayHolder<_>`
4242
LL | let mut array = ArrayHolder::new();
4343
| ^^^^^^^^^ ----------- type must be known at this point
4444
|
45-
note: required by a bound in `ArrayHolder`
45+
note: required by a const generic parameter in `ArrayHolder`
4646
--> $DIR/issue-62504.rs:14:20
4747
|
4848
LL | struct ArrayHolder<const X: usize>([u32; X]);
49-
| ^^^^^^^^^^^^^^ required by this bound in `ArrayHolder`
49+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `ArrayHolder`
5050
help: consider giving `array` an explicit type, where the value of const parameter `X` is specified
5151
|
5252
LL | let mut array: ArrayHolder<X> = ArrayHolder::new();

tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ error[E0284]: type annotations needed for `ArrayHolder<_>`
2828
LL | let mut array = ArrayHolder::new();
2929
| ^^^^^^^^^ ------------------ type must be known at this point
3030
|
31-
note: required by a bound in `ArrayHolder::<X>::new`
31+
note: required by a const generic parameter in `ArrayHolder::<X>::new`
3232
--> $DIR/issue-62504.rs:16:6
3333
|
3434
LL | impl<const X: usize> ArrayHolder<X> {
35-
| ^^^^^^^^^^^^^^ required by this bound in `ArrayHolder::<X>::new`
35+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `ArrayHolder::<X>::new`
3636
LL | pub const fn new() -> Self {
3737
| --- required by a bound in this associated function
3838
help: consider giving `array` an explicit type, where the value of const parameter `X` is specified
@@ -46,11 +46,11 @@ error[E0284]: type annotations needed for `ArrayHolder<_>`
4646
LL | let mut array = ArrayHolder::new();
4747
| ^^^^^^^^^ ----------- type must be known at this point
4848
|
49-
note: required by a bound in `ArrayHolder`
49+
note: required by a const generic parameter in `ArrayHolder`
5050
--> $DIR/issue-62504.rs:14:20
5151
|
5252
LL | struct ArrayHolder<const X: usize>([u32; X]);
53-
| ^^^^^^^^^^^^^^ required by this bound in `ArrayHolder`
53+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `ArrayHolder`
5454
help: consider giving `array` an explicit type, where the value of const parameter `X` is specified
5555
|
5656
LL | let mut array: ArrayHolder<X> = ArrayHolder::new();

tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0284]: type annotations needed
44
LL | use_dyn(&());
55
| ^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `use_dyn`
66
|
7-
note: required by a bound in `use_dyn`
7+
note: required by a const generic parameter in `use_dyn`
88
--> $DIR/object-safety-ok-infer-err.rs:14:12
99
|
1010
LL | fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
11-
| ^^^^^^^^^^^^^^ required by this bound in `use_dyn`
11+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `use_dyn`
1212
help: consider specifying the generic argument
1313
|
1414
LL | use_dyn::<N>(&());

tests/ui/const-generics/infer/cannot-infer-const-args.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0284]: type annotations needed
44
LL | foo();
55
| ^^^ cannot infer the value of the const parameter `X` declared on the function `foo`
66
|
7-
note: required by a bound in `foo`
7+
note: required by a const generic parameter in `foo`
88
--> $DIR/cannot-infer-const-args.rs:1:8
99
|
1010
LL | fn foo<const X: usize>() -> usize {
11-
| ^^^^^^^^^^^^^^ required by this bound in `foo`
11+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `foo`
1212
help: consider specifying the generic argument
1313
|
1414
LL | foo::<X>();

tests/ui/const-generics/infer/issue-77092.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0284]: type annotations needed
44
LL | println!("{:?}", take_array_from_mut(&mut arr, i));
55
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut`
66
|
7-
note: required by a bound in `take_array_from_mut`
7+
note: required by a const generic parameter in `take_array_from_mut`
88
--> $DIR/issue-77092.rs:3:27
99
|
1010
LL | fn take_array_from_mut<T, const N: usize>(data: &mut [T], start: usize) -> &mut [T; N] {
11-
| ^^^^^^^^^^^^^^ required by this bound in `take_array_from_mut`
11+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `take_array_from_mut`
1212
help: consider specifying the generic arguments
1313
|
1414
LL | println!("{:?}", take_array_from_mut::<i32, N>(&mut arr, i));

tests/ui/const-generics/infer/method-chain.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ error[E0284]: type annotations needed
44
LL | Foo.bar().bar().bar().bar().baz();
55
| ^^^ cannot infer the value of the const parameter `N` declared on the method `baz`
66
|
7-
note: required by a bound in `Foo::baz`
7+
note: required by a const generic parameter in `Foo::baz`
88
--> $DIR/method-chain.rs:8:12
99
|
1010
LL | fn baz<const N: usize>(self) -> Foo {
11-
| ^^^^^^^^^^^^^^ required by this bound in `Foo::baz`
11+
| ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo::baz`
1212
help: consider specifying the generic argument
1313
|
1414
LL | Foo.bar().bar().bar().bar().baz::<N>();

0 commit comments

Comments
 (0)