Rollup merge of #121258 - fmease:assoc-const-eq-reject-overly-generic-tys, r=compiler-errors
Reject overly generic assoc const binding types Split off from #119385 to make #119385 easier to review. --- In the *instantiated* type of assoc const bindings 1. reject **early-bound generic params** * Provide a rich error message instead of ICE'ing ([#108271](https://github.com/rust-lang/rust/issues/108271)). * This is a temporary and semi-artificial restriction until the arrival of *generic const generics*. * It's quite possible that rustc could already perfectly support this subset of generic const generics if we just removed some checks (some `.no_bound_vars().expect(…)`) but even if that was the case, I'd rather gate it behind a new feature flag. Reporting an error instead of ICE'ing is a good first step towards an eventual feature gate error. 2. reject **escaping late-bound generic params** * They lead to ICEs before & I'm pretty sure that they remain incorrect even in a world with *generic const generics* --- Together with #118668 & #119385, this supersedes #118360. Fixes #108271.
This commit is contained in:
commit
05f763344d
10 changed files with 463 additions and 11 deletions
|
@ -118,6 +118,11 @@ hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
|
|||
.label = overflowed on value after {$discr}
|
||||
.note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
|
||||
|
||||
hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding =
|
||||
the type of the associated constant `{$assoc_const}` cannot capture late-bound generic parameters
|
||||
.label = its type cannot capture the late-bound {$var_def_kind} `{$var_name}`
|
||||
.var_defined_here_label = the late-bound {$var_def_kind} `{$var_name}` is defined here
|
||||
|
||||
hir_analysis_field_already_declared =
|
||||
field `{$field_name}` is already declared
|
||||
.label = field already declared
|
||||
|
@ -316,6 +321,22 @@ hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot captur
|
|||
.label = `impl Trait` implicitly captures all lifetimes in scope
|
||||
.note = lifetime declared here
|
||||
|
||||
hir_analysis_param_in_ty_of_assoc_const_binding =
|
||||
the type of the associated constant `{$assoc_const}` must not depend on {$param_category ->
|
||||
[self] `Self`
|
||||
[synthetic] `impl Trait`
|
||||
*[normal] generic parameters
|
||||
}
|
||||
.label = its type must not depend on {$param_category ->
|
||||
[self] `Self`
|
||||
[synthetic] `impl Trait`
|
||||
*[normal] the {$param_def_kind} `{$param_name}`
|
||||
}
|
||||
.param_defined_here_label = {$param_category ->
|
||||
[synthetic] the `impl Trait` is specified here
|
||||
*[normal] the {$param_def_kind} `{$param_name}` is defined here
|
||||
}
|
||||
|
||||
hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
|
||||
.help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
|
||||
|
||||
|
@ -432,6 +453,8 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de
|
|||
.label = needs at most one field with non-trivial size or alignment, but has {$field_count}
|
||||
.labels = this field has non-zero size or requires alignment
|
||||
|
||||
hir_analysis_ty_of_assoc_const_binding_note = `{$assoc_const}` has type `{$ty}`
|
||||
|
||||
hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
|
||||
.label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`)
|
||||
.note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::{codes::*, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::ty::{self as ty, Ty};
|
||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
|
||||
|
@ -433,14 +436,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
binding.kind
|
||||
{
|
||||
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
|
||||
// Since the arguments passed to the alias type above may contain early-bound
|
||||
// generic parameters, the instantiated type may contain some as well.
|
||||
// Therefore wrap it in `EarlyBinder`.
|
||||
// FIXME(fmease): Reject escaping late-bound vars.
|
||||
tcx.feed_anon_const_type(
|
||||
anon_const.def_id,
|
||||
ty::EarlyBinder::bind(ty.skip_binder()),
|
||||
);
|
||||
let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, binding.hir_id);
|
||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
|
||||
alias_ty
|
||||
|
@ -530,3 +527,167 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
|
||||
///
|
||||
/// FIXME(const_generics): This is a temporary and semi-artifical restriction until the
|
||||
/// arrival of *generic const generics*[^1].
|
||||
///
|
||||
/// It might actually be possible that we can already support early-bound generic params
|
||||
/// in such types if we just lifted some more checks in other places, too, for example
|
||||
/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should
|
||||
/// probably gate this behind another feature flag.
|
||||
///
|
||||
/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
|
||||
fn check_assoc_const_binding_type<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
assoc_const: Ident,
|
||||
ty: ty::Binder<'tcx, Ty<'tcx>>,
|
||||
hir_id: hir::HirId,
|
||||
) -> Ty<'tcx> {
|
||||
// We can't perform the checks for early-bound params during name resolution unlike E0770
|
||||
// because this information depends on *type* resolution.
|
||||
// We can't perform these checks in `resolve_bound_vars` either for the same reason.
|
||||
// Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
|
||||
// resolved type of `Trait::C` in order to know if it references `'a` or not.
|
||||
|
||||
let ty = ty.skip_binder();
|
||||
if !ty.has_param() && !ty.has_escaping_bound_vars() {
|
||||
return ty;
|
||||
}
|
||||
|
||||
let mut collector = GenericParamAndBoundVarCollector {
|
||||
tcx,
|
||||
params: Default::default(),
|
||||
vars: Default::default(),
|
||||
depth: ty::INNERMOST,
|
||||
};
|
||||
let mut guar = ty.visit_with(&mut collector).break_value();
|
||||
|
||||
let ty_note = ty
|
||||
.make_suggestable(tcx, false)
|
||||
.map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
|
||||
|
||||
let enclosing_item_owner_id = tcx
|
||||
.hir()
|
||||
.parent_owner_iter(hir_id)
|
||||
.find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
|
||||
.unwrap();
|
||||
let generics = tcx.generics_of(enclosing_item_owner_id);
|
||||
for index in collector.params {
|
||||
let param = generics.param_at(index as _, tcx);
|
||||
let is_self_param = param.name == rustc_span::symbol::kw::SelfUpper;
|
||||
guar.get_or_insert(tcx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
|
||||
span: assoc_const.span,
|
||||
assoc_const,
|
||||
param_name: param.name,
|
||||
param_def_kind: tcx.def_descr(param.def_id),
|
||||
param_category: if is_self_param {
|
||||
"self"
|
||||
} else if param.kind.is_synthetic() {
|
||||
"synthetic"
|
||||
} else {
|
||||
"normal"
|
||||
},
|
||||
param_defined_here_label:
|
||||
(!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
|
||||
ty_note,
|
||||
}));
|
||||
}
|
||||
for (var_def_id, var_name) in collector.vars {
|
||||
guar.get_or_insert(tcx.dcx().emit_err(
|
||||
crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
|
||||
span: assoc_const.span,
|
||||
assoc_const,
|
||||
var_name,
|
||||
var_def_kind: tcx.def_descr(var_def_id),
|
||||
var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
|
||||
ty_note,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
|
||||
struct GenericParamAndBoundVarCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
params: FxIndexSet<u32>,
|
||||
vars: FxIndexSet<(DefId, Symbol)>,
|
||||
depth: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'tcx> {
|
||||
type Result = ControlFlow<ErrorGuaranteed>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
binder: &ty::Binder<'tcx, T>,
|
||||
) -> Self::Result {
|
||||
self.depth.shift_in(1);
|
||||
let result = binder.super_visit_with(self);
|
||||
self.depth.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
match ty.kind() {
|
||||
ty::Param(param) => {
|
||||
self.params.insert(param.index);
|
||||
}
|
||||
ty::Bound(db, bt) if *db >= self.depth => {
|
||||
self.vars.insert(match bt.kind {
|
||||
ty::BoundTyKind::Param(def_id, name) => (def_id, name),
|
||||
ty::BoundTyKind::Anon => {
|
||||
let reported = self
|
||||
.tcx
|
||||
.dcx()
|
||||
.delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
|
||||
return ControlFlow::Break(reported);
|
||||
}
|
||||
});
|
||||
}
|
||||
_ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
|
||||
_ => {}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
|
||||
match re.kind() {
|
||||
ty::ReEarlyParam(param) => {
|
||||
self.params.insert(param.index);
|
||||
}
|
||||
ty::ReBound(db, br) if db >= self.depth => {
|
||||
self.vars.insert(match br.kind {
|
||||
ty::BrNamed(def_id, name) => (def_id, name),
|
||||
ty::BrAnon | ty::BrEnv => {
|
||||
let guar = self
|
||||
.tcx
|
||||
.dcx()
|
||||
.delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
|
||||
return ControlFlow::Break(guar);
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
|
||||
match ct.kind() {
|
||||
ty::ConstKind::Param(param) => {
|
||||
self.params.insert(param.index);
|
||||
}
|
||||
ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => {
|
||||
let guar = self.tcx.dcx().delayed_bug("unexpected escaping late-bound const var");
|
||||
return ControlFlow::Break(guar);
|
||||
}
|
||||
_ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
|
||||
_ => {}
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -295,6 +295,44 @@ pub struct AssocTypeBindingNotAllowed {
|
|||
pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_param_in_ty_of_assoc_const_binding)]
|
||||
pub(crate) struct ParamInTyOfAssocConstBinding<'tcx> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub assoc_const: Ident,
|
||||
pub param_name: Symbol,
|
||||
pub param_def_kind: &'static str,
|
||||
pub param_category: &'static str,
|
||||
#[label(hir_analysis_param_defined_here_label)]
|
||||
pub param_defined_here_label: Option<Span>,
|
||||
#[subdiagnostic]
|
||||
pub ty_note: Option<TyOfAssocConstBindingNote<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic, Clone, Copy)]
|
||||
#[note(hir_analysis_ty_of_assoc_const_binding_note)]
|
||||
pub(crate) struct TyOfAssocConstBindingNote<'tcx> {
|
||||
pub assoc_const: Ident,
|
||||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding)]
|
||||
pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub assoc_const: Ident,
|
||||
pub var_name: Symbol,
|
||||
pub var_def_kind: &'static str,
|
||||
#[label(hir_analysis_var_defined_here_label)]
|
||||
pub var_defined_here_label: Span,
|
||||
#[subdiagnostic]
|
||||
pub ty_note: Option<TyOfAssocConstBindingNote<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[help(hir_analysis_parenthesized_fn_trait_expansion)]
|
||||
pub struct ParenthesizedFnTraitExpansion {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// Check that we eventually catch types of assoc const bounds
|
||||
// (containing late-bound vars) that are ill-formed.
|
||||
#![feature(associated_const_equality)]
|
||||
|
||||
trait Trait<T> {
|
||||
const K: T;
|
||||
}
|
||||
|
||||
fn take(
|
||||
_: impl Trait<
|
||||
<<for<'a> fn(&'a str) -> &'a str as Project>::Out as Discard>::Out,
|
||||
K = { () }
|
||||
>,
|
||||
) {}
|
||||
//~^^^^^^ ERROR implementation of `Project` is not general enough
|
||||
//~^^^^ ERROR higher-ranked subtype error
|
||||
//~| ERROR higher-ranked subtype error
|
||||
|
||||
trait Project { type Out; }
|
||||
impl<T> Project for fn(T) -> T { type Out = T; }
|
||||
|
||||
trait Discard { type Out; }
|
||||
impl<T: ?Sized> Discard for T { type Out = (); }
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,25 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13
|
||||
|
|
||||
LL | K = { () }
|
||||
| ^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13
|
||||
|
|
||||
LL | K = { () }
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Project` is not general enough
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:9:4
|
||||
|
|
||||
LL | fn take(
|
||||
| ^^^^ implementation of `Project` is not general enough
|
||||
|
|
||||
= note: `Project` would have to be implemented for the type `for<'a> fn(&'a str) -> &'a str`
|
||||
= note: ...but `Project` is actually implemented for the type `fn(&'0 str) -> &'0 str`, for some specific lifetime `'0`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
22
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs
Normal file
22
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Check that we don't reject non-escaping late-bound vars in the type of assoc const bindings.
|
||||
// There's no reason why we should disallow them.
|
||||
//
|
||||
//@ check-pass
|
||||
|
||||
#![feature(associated_const_equality)]
|
||||
|
||||
trait Trait<T> {
|
||||
const K: T;
|
||||
}
|
||||
|
||||
fn take(
|
||||
_: impl Trait<
|
||||
<for<'a> fn(&'a str) -> &'a str as Discard>::Out,
|
||||
K = { () }
|
||||
>,
|
||||
) {}
|
||||
|
||||
trait Discard { type Out; }
|
||||
impl<T: ?Sized> Discard for T { type Out = (); }
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,15 @@
|
|||
// Detect and reject escaping late-bound generic params in
|
||||
// the type of assoc consts used in an equality bound.
|
||||
#![feature(associated_const_equality)]
|
||||
|
||||
trait Trait<'a> {
|
||||
const K: &'a ();
|
||||
}
|
||||
|
||||
fn take(_: impl for<'r> Trait<'r, K = { &() }>) {}
|
||||
//~^ ERROR the type of the associated constant `K` cannot capture late-bound generic parameters
|
||||
//~| NOTE its type cannot capture the late-bound lifetime parameter `'r`
|
||||
//~| NOTE the late-bound lifetime parameter `'r` is defined here
|
||||
//~| NOTE `K` has type `&'r ()`
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
error: the type of the associated constant `K` cannot capture late-bound generic parameters
|
||||
--> $DIR/assoc-const-eq-esc-bound-var-in-ty.rs:9:35
|
||||
|
|
||||
LL | fn take(_: impl for<'r> Trait<'r, K = { &() }>) {}
|
||||
| -- ^ its type cannot capture the late-bound lifetime parameter `'r`
|
||||
| |
|
||||
| the late-bound lifetime parameter `'r` is defined here
|
||||
|
|
||||
= note: `K` has type `&'r ()`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
55
tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs
Normal file
55
tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Regression test for issue #108271.
|
||||
// Detect and reject generic params in the type of assoc consts used in an equality bound.
|
||||
#![feature(associated_const_equality)]
|
||||
|
||||
trait Trait<'a, T: 'a, const N: usize> {
|
||||
const K: &'a [T; N];
|
||||
}
|
||||
|
||||
fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the lifetime parameter `'r`
|
||||
//~| NOTE the lifetime parameter `'r` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the type parameter `A`
|
||||
//~| NOTE the type parameter `A` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the const parameter `Q`
|
||||
//~| NOTE the const parameter `Q` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
|
||||
trait Project {
|
||||
const SELF: Self;
|
||||
}
|
||||
|
||||
fn take1(_: impl Project<SELF = {}>) {}
|
||||
//~^ ERROR the type of the associated constant `SELF` must not depend on `impl Trait`
|
||||
//~| NOTE its type must not depend on `impl Trait`
|
||||
//~| NOTE the `impl Trait` is specified here
|
||||
|
||||
fn take2<P: Project<SELF = {}>>(_: P) {}
|
||||
//~^ ERROR the type of the associated constant `SELF` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the type parameter `P`
|
||||
//~| NOTE the type parameter `P` is defined here
|
||||
//~| NOTE `SELF` has type `P`
|
||||
|
||||
trait Iface<'r> {
|
||||
//~^ NOTE the lifetime parameter `'r` is defined here
|
||||
type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the lifetime parameter `'r`
|
||||
//~| NOTE `K` has type `&'r [Self; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on `Self`
|
||||
//~| NOTE its type must not depend on `Self`
|
||||
//~| NOTE `K` has type `&'r [Self; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the const parameter `Q`
|
||||
//~| NOTE the const parameter `Q` is defined here
|
||||
//~| NOTE `K` has type `&'r [Self; Q]`
|
||||
where
|
||||
Self: Sized + 'r;
|
||||
}
|
||||
|
||||
fn main() {}
|
76
tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr
Normal file
76
tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr
Normal file
|
@ -0,0 +1,76 @@
|
|||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:9:61
|
||||
|
|
||||
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:9:61
|
||||
|
|
||||
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:9:61
|
||||
|
|
||||
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `SELF` must not depend on `impl Trait`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:27:26
|
||||
|
|
||||
LL | fn take1(_: impl Project<SELF = {}>) {}
|
||||
| -------------^^^^------
|
||||
| | |
|
||||
| | its type must not depend on `impl Trait`
|
||||
| the `impl Trait` is specified here
|
||||
|
||||
error: the type of the associated constant `SELF` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:32:21
|
||||
|
|
||||
LL | fn take2<P: Project<SELF = {}>>(_: P) {}
|
||||
| - ^^^^ its type must not depend on the type parameter `P`
|
||||
| |
|
||||
| the type parameter `P` is defined here
|
||||
|
|
||||
= note: `SELF` has type `P`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:40:52
|
||||
|
|
||||
LL | trait Iface<'r> {
|
||||
| -- the lifetime parameter `'r` is defined here
|
||||
LL |
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| ^ its type must not depend on the lifetime parameter `'r`
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on `Self`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:40:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| ^ its type must not depend on `Self`
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:40:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
Loading…
Add table
Reference in a new issue