Auto merge of #125915 - camelid:const-arg-refactor, r=BoxyUwU
Represent type-level consts with new-and-improved `hir::ConstArg` ### Summary This is a step toward `min_generic_const_exprs`. We now represent all const generic arguments using an enum that differentiates between const *paths* (temporarily just bare const params) and arbitrary anon consts that may perform computations. This will enable us to cleanly implement the `min_generic_const_args` plan of allowing the use of generics in paths used as const args, while disallowing their use in arbitrary anon consts. Here is a summary of the salient aspects of this change: - Add `current_def_id_parent` to `LoweringContext` This is needed to track anon const parents properly once we implement `ConstArgKind::Path` (which requires moving anon const def-creation outside of `DefCollector`). - Create `hir::ConstArgKind` enum with `Path` and `Anon` variants. Use it in the existing `hir::ConstArg` struct, replacing the previous `hir::AnonConst` field. - Use `ConstArg` for all instances of const args. Specifically, use it instead of `AnonConst` for assoc item constraints, array lengths, and const param defaults. - Some `ast::AnonConst`s now have their `DefId`s created in rustc_ast_lowering rather than `DefCollector`. This is because in some cases they will end up becoming a `ConstArgKind::Path` instead, which has no `DefId`. We have to solve this in a hacky way where we guess whether the `AnonConst` could end up as a path const since we can't know for sure until after name resolution (`N` could refer to a free const or a nullary struct). If it has no chance as being a const param, then we create a `DefId` in `DefCollector` -- otherwise we decide during ast_lowering. This will have to be updated once all path consts use `ConstArgKind::Path`. - We explicitly use `ConstArgHasType` for array lengths, rather than implicitly relying on anon const type feeding -- this is due to the addition of `ConstArgKind::Path`. - Some tests have their outputs changed, but the changes are for the most part minor (including removing duplicate or almost-duplicate errors). One test now ICEs, but it is for an incomplete, unstable feature and is now tracked at https://github.com/rust-lang/rust/issues/127009. ### Followup items post-merge - Use `ConstArgKind::Path` for all const paths, not just const params. - Fix (no github dont close this issue) #127009 - If a path in generic args doesn't resolve as a type, try to resolve as a const instead (do this in rustc_resolve). Then remove the special-casing from `rustc_ast_lowering`, so that all params will automatically be lowered as `ConstArgKind::Path`. - (?) Consider making `const_evaluatable_unchecked` a hard error, or at least trying it in crater r? `@BoxyUwU`
This commit is contained in:
commit
8c3a94a1c7
72 changed files with 853 additions and 543 deletions
|
@ -187,7 +187,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
.emit();
|
||||
}
|
||||
hir::InlineAsmOperand::Const {
|
||||
anon_const: self.lower_anon_const(anon_const),
|
||||
anon_const: self.lower_anon_const_to_anon_const(anon_const),
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Sym { sym } => {
|
||||
|
@ -222,18 +222,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
|
||||
// Wrap the expression in an AnonConst.
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
*op_sp,
|
||||
);
|
||||
// HACK(min_generic_const_args): see lower_anon_const
|
||||
if !expr.is_potential_trivial_const_arg() {
|
||||
self.create_def(
|
||||
parent_def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
*op_sp,
|
||||
);
|
||||
}
|
||||
let anon_const = AnonConst { id: node_id, value: P(expr) };
|
||||
hir::InlineAsmOperand::SymFn {
|
||||
anon_const: self.lower_anon_const(&anon_const),
|
||||
anon_const: self.lower_anon_const_to_anon_const(&anon_const),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,10 +75,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let kind = match &e.kind {
|
||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||
ExprKind::ConstBlock(c) => {
|
||||
let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
|
||||
def_id: this.local_def_id(c.id),
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
let c = self.with_new_scopes(c.value.span, |this| {
|
||||
let def_id = this.local_def_id(c.id);
|
||||
hir::ConstBlock {
|
||||
def_id,
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(c.value.span, Some(&c.value))
|
||||
}),
|
||||
}
|
||||
});
|
||||
hir::ExprKind::ConstBlock(c)
|
||||
}
|
||||
|
@ -377,17 +382,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let mut generic_args = ThinVec::new();
|
||||
for (idx, arg) in args.into_iter().enumerate() {
|
||||
if legacy_args_idx.contains(&idx) {
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
f.span,
|
||||
);
|
||||
// HACK(min_generic_const_args): see lower_anon_const
|
||||
if !arg.is_potential_trivial_const_arg() {
|
||||
// Add a definition for the in-band const def.
|
||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
|
||||
}
|
||||
|
||||
let anon_const = AnonConst { id: node_id, value: arg };
|
||||
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
|
||||
|
@ -622,6 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
coroutine_source: hir::CoroutineSource,
|
||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let closure_def_id = self.local_def_id(closure_node_id);
|
||||
let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);
|
||||
|
||||
// The `async` desugaring takes a resume argument and maintains a `task_context`,
|
||||
|
@ -672,22 +675,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
lifetime_elision_allowed: false,
|
||||
});
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
let body = self.with_def_id_parent(closure_def_id, move |this| {
|
||||
this.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
if task_context.is_some() {
|
||||
this.task_context = task_context;
|
||||
}
|
||||
let res = body(this);
|
||||
this.task_context = old_ctx;
|
||||
let old_ctx = this.task_context;
|
||||
if task_context.is_some() {
|
||||
this.task_context = task_context;
|
||||
}
|
||||
let res = body(this);
|
||||
this.task_context = old_ctx;
|
||||
|
||||
(params, res)
|
||||
(params, res)
|
||||
})
|
||||
});
|
||||
|
||||
// `static |<_task_context?>| -> <return_ty> { <body> }`:
|
||||
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_node_id),
|
||||
def_id: closure_def_id,
|
||||
binder: hir::ClosureBinder::Default,
|
||||
capture_clause,
|
||||
bound_generic_params: &[],
|
||||
|
@ -966,27 +971,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn_decl_span: Span,
|
||||
fn_arg_span: Span,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let closure_def_id = self.local_def_id(closure_id);
|
||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||
let mut coroutine_kind = if this
|
||||
.attrs
|
||||
.get(&closure_hir_id.local_id)
|
||||
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
||||
{
|
||||
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
this.coroutine_kind = coroutine_kind;
|
||||
let e = this.lower_expr_mut(body);
|
||||
coroutine_kind = this.coroutine_kind;
|
||||
e
|
||||
});
|
||||
let coroutine_option =
|
||||
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||
(body_id, coroutine_option)
|
||||
this.with_def_id_parent(closure_def_id, move |this| {
|
||||
let mut coroutine_kind = if this
|
||||
.attrs
|
||||
.get(&closure_hir_id.local_id)
|
||||
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
||||
{
|
||||
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
this.coroutine_kind = coroutine_kind;
|
||||
let e = this.lower_expr_mut(body);
|
||||
coroutine_kind = this.coroutine_kind;
|
||||
e
|
||||
});
|
||||
let coroutine_option =
|
||||
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||
(body_id, coroutine_option)
|
||||
})
|
||||
});
|
||||
|
||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||
|
@ -994,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
|
||||
|
||||
let c = self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_id),
|
||||
def_id: closure_def_id,
|
||||
binder: binder_clause,
|
||||
capture_clause,
|
||||
bound_generic_params,
|
||||
|
@ -1066,6 +1074,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn_decl_span: Span,
|
||||
fn_arg_span: Span,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let closure_def_id = self.local_def_id(closure_id);
|
||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
assert_matches!(
|
||||
|
@ -1075,27 +1084,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
);
|
||||
|
||||
let body = self.with_new_scopes(fn_decl_span, |this| {
|
||||
let inner_decl =
|
||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||
this.with_def_id_parent(closure_def_id, |this| {
|
||||
let inner_decl =
|
||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||
|
||||
// Transform `async |x: u8| -> X { ... }` into
|
||||
// `|x: u8| || -> X { ... }`.
|
||||
let body_id = this.lower_body(|this| {
|
||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||
&inner_decl,
|
||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||
fn_decl_span,
|
||||
body.span,
|
||||
coroutine_kind,
|
||||
hir::CoroutineSource::Closure,
|
||||
);
|
||||
// Transform `async |x: u8| -> X { ... }` into
|
||||
// `|x: u8| || -> X { ... }`.
|
||||
let body_id = this.lower_body(|this| {
|
||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||
&inner_decl,
|
||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||
fn_decl_span,
|
||||
body.span,
|
||||
coroutine_kind,
|
||||
hir::CoroutineSource::Closure,
|
||||
);
|
||||
|
||||
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
||||
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
||||
|
||||
(parameters, expr)
|
||||
});
|
||||
body_id
|
||||
(parameters, expr)
|
||||
});
|
||||
body_id
|
||||
})
|
||||
});
|
||||
|
||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||
|
@ -1106,7 +1117,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
|
||||
|
||||
let c = self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_id),
|
||||
def_id: closure_def_id,
|
||||
binder: binder_clause,
|
||||
capture_clause,
|
||||
bound_generic_params,
|
||||
|
|
|
@ -181,7 +181,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
intravisit::walk_generic_param(self, param);
|
||||
}
|
||||
|
||||
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
|
||||
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir ConstArg<'hir>) {
|
||||
self.with_parent(param, |this| {
|
||||
intravisit::walk_const_param_default(this, ct);
|
||||
})
|
||||
|
@ -229,6 +229,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
|
||||
// FIXME: use real span?
|
||||
self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
|
||||
|
||||
self.with_parent(constant.hir_id, |this| {
|
||||
|
@ -244,6 +245,15 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
|
||||
// FIXME: use real span?
|
||||
self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg));
|
||||
|
||||
self.with_parent(const_arg.hir_id, |this| {
|
||||
intravisit::walk_const_arg(this, const_arg);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
|
||||
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
|
||||
|
||||
|
|
|
@ -61,7 +61,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
|
||||
for (def_id, info) in lctx.children {
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(matches!(owner, hir::MaybeOwner::Phantom));
|
||||
debug_assert!(
|
||||
matches!(owner, hir::MaybeOwner::Phantom),
|
||||
"duplicate copy of {def_id:?} in lctx.children"
|
||||
);
|
||||
*owner = info;
|
||||
}
|
||||
}
|
||||
|
@ -713,7 +716,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir_id,
|
||||
def_id: self.local_def_id(v.id),
|
||||
data: self.lower_variant_data(hir_id, &v.data),
|
||||
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
|
||||
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
|
||||
ident: self.lower_ident(v.ident),
|
||||
span: self.lower_span(v.span),
|
||||
}
|
||||
|
@ -1601,7 +1604,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
if let Some((span, hir_id, def_id)) = host_param_parts {
|
||||
let const_node_id = self.next_node_id();
|
||||
let anon_const =
|
||||
let anon_const_did =
|
||||
self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
|
||||
let const_id = self.next_id();
|
||||
|
@ -1609,7 +1612,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let bool_id = self.next_id();
|
||||
|
||||
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||
self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));
|
||||
self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
|
||||
|
||||
let const_body = self.lower_body(|this| {
|
||||
(
|
||||
|
@ -1624,6 +1627,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
)
|
||||
});
|
||||
|
||||
let default_ac = self.arena.alloc(hir::AnonConst {
|
||||
def_id: anon_const_did,
|
||||
hir_id: const_id,
|
||||
body: const_body,
|
||||
span,
|
||||
});
|
||||
let default_ct = self.arena.alloc(hir::ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Anon(default_ac),
|
||||
is_desugared_from_effects: false,
|
||||
});
|
||||
let param = hir::GenericParam {
|
||||
def_id,
|
||||
hir_id,
|
||||
|
@ -1648,12 +1662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
)),
|
||||
)),
|
||||
// FIXME(effects) we might not need a default.
|
||||
default: Some(self.arena.alloc(hir::AnonConst {
|
||||
def_id: anon_const,
|
||||
hir_id: const_id,
|
||||
body: const_body,
|
||||
span,
|
||||
})),
|
||||
default: Some(default_ct),
|
||||
is_host_effect: true,
|
||||
synthetic: true,
|
||||
},
|
||||
|
|
|
@ -120,6 +120,18 @@ struct LoweringContext<'a, 'hir> {
|
|||
is_in_dyn_type: bool,
|
||||
|
||||
current_hir_id_owner: hir::OwnerId,
|
||||
/// Why do we need this in addition to [`Self::current_hir_id_owner`]?
|
||||
///
|
||||
/// Currently (as of June 2024), anonymous constants are not HIR owners; however,
|
||||
/// they do get their own DefIds. Some of these DefIds have to be created during
|
||||
/// AST lowering, rather than def collection, because we can't tell until after
|
||||
/// name resolution whether an anonymous constant will end up instead being a
|
||||
/// [`hir::ConstArgKind::Path`]. However, to compute which generics are
|
||||
/// available to an anonymous constant nested inside another, we need to make
|
||||
/// sure that the parent is recorded as the parent anon const, not the enclosing
|
||||
/// item. So we need to track parent defs differently from HIR owners, since they
|
||||
/// will be finer-grained in the case of anon consts.
|
||||
current_def_id_parent: LocalDefId,
|
||||
item_local_id_counter: hir::ItemLocalId,
|
||||
trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
|
||||
|
||||
|
@ -162,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
attrs: SortedMap::default(),
|
||||
children: Vec::default(),
|
||||
current_hir_id_owner: hir::CRATE_OWNER_ID,
|
||||
current_def_id_parent: CRATE_DEF_ID,
|
||||
item_local_id_counter: hir::ItemLocalId::ZERO,
|
||||
node_id_to_local_id: Default::default(),
|
||||
trait_map: Default::default(),
|
||||
|
@ -592,7 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
|
||||
debug_assert_eq!(_old, None);
|
||||
|
||||
let item = f(self);
|
||||
let item = self.with_def_id_parent(def_id, f);
|
||||
debug_assert_eq!(def_id, item.def_id().def_id);
|
||||
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
|
@ -612,6 +625,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.children.push((def_id, hir::MaybeOwner::Owner(info)));
|
||||
}
|
||||
|
||||
fn with_def_id_parent<T>(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||
let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent);
|
||||
let result = f(self);
|
||||
self.current_def_id_parent = current_def_id_parent;
|
||||
result
|
||||
}
|
||||
|
||||
/// Installs the remapping `remap` in scope while `f` is being executed.
|
||||
/// This causes references to the `LocalDefId` keys to be changed to
|
||||
/// refer to the values instead.
|
||||
|
@ -806,7 +826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
LifetimeRes::Fresh { param, kind, .. } => {
|
||||
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||
let _def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
param,
|
||||
kw::UnderscoreLifetime,
|
||||
DefKind::LifetimeParam,
|
||||
|
@ -1044,7 +1064,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
AssocItemConstraintKind::Equality { term } => {
|
||||
let term = match term {
|
||||
Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
|
||||
Term::Const(c) => self.lower_anon_const(c).into(),
|
||||
Term::Const(c) => self.lower_anon_const_to_const_arg(c).into(),
|
||||
};
|
||||
hir::AssocItemConstraintKind::Equality { term }
|
||||
}
|
||||
|
@ -1150,42 +1170,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ty,
|
||||
);
|
||||
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(ty.span);
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
let def_id = self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty.id,
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id: this.lower_node_id(node_id),
|
||||
body: this
|
||||
.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||
span,
|
||||
})
|
||||
});
|
||||
return GenericArg::Const(ConstArg {
|
||||
value: ct,
|
||||
is_desugared_from_effects: false,
|
||||
});
|
||||
let ct =
|
||||
self.lower_const_path_to_const_arg(path, res, ty.id, ty.span);
|
||||
return GenericArg::Const(ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1193,10 +1180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
GenericArg::Type(self.lower_ty(ty, itctx))
|
||||
}
|
||||
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
|
||||
value: self.lower_anon_const(ct),
|
||||
is_desugared_from_effects: false,
|
||||
}),
|
||||
ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1355,7 +1339,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
TyKind::Array(ty, length) => {
|
||||
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
|
||||
}
|
||||
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
|
||||
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
|
||||
TyKind::TraitObject(bounds, kind) => {
|
||||
let mut lifetime_bound = None;
|
||||
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
||||
|
@ -1429,7 +1413,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
);
|
||||
|
||||
self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
*def_node_id,
|
||||
ident.name,
|
||||
DefKind::TyParam,
|
||||
|
@ -1637,7 +1621,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
||||
) -> hir::TyKind<'hir> {
|
||||
let opaque_ty_def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
opaque_ty_node_id,
|
||||
kw::Empty,
|
||||
DefKind::OpaqueTy,
|
||||
|
@ -2222,7 +2206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
false
|
||||
}
|
||||
})
|
||||
.map(|def| self.lower_anon_const(def));
|
||||
.map(|def| self.lower_anon_const_to_const_arg(def));
|
||||
|
||||
(
|
||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||
|
@ -2360,19 +2344,153 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
"using `_` for array lengths is unstable",
|
||||
)
|
||||
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
|
||||
hir::ArrayLen::Body(self.lower_anon_const(c))
|
||||
hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c))
|
||||
}
|
||||
}
|
||||
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
|
||||
_ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
|
||||
self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst {
|
||||
def_id: this.local_def_id(c.id),
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
span: this.lower_span(c.value.span),
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_const_path_to_const_arg(
|
||||
&mut self,
|
||||
path: &Path,
|
||||
res: Res<NodeId>,
|
||||
ty_id: NodeId,
|
||||
span: Span,
|
||||
) -> &'hir hir::ConstArg<'hir> {
|
||||
let ct_kind = match res {
|
||||
Res::Def(DefKind::ConstParam, _) => {
|
||||
let qpath = self.lower_qpath(
|
||||
ty_id,
|
||||
&None,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
hir::ConstArgKind::Path(qpath)
|
||||
}
|
||||
_ => {
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(span);
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
let def_id =
|
||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty_id,
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(path_expr.span, Some(&path_expr))
|
||||
}),
|
||||
span,
|
||||
})
|
||||
});
|
||||
hir::ConstArgKind::Anon(ct)
|
||||
}
|
||||
};
|
||||
|
||||
self.arena.alloc(hir::ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: ct_kind,
|
||||
is_desugared_from_effects: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// See [`hir::ConstArg`] for when to use this function vs
|
||||
/// [`Self::lower_anon_const_to_anon_const`].
|
||||
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
|
||||
self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
|
||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
|
||||
&& let [stmt] = block.stmts.as_slice()
|
||||
&& let StmtKind::Expr(expr) = &stmt.kind
|
||||
&& let ExprKind::Path(..) = &expr.kind
|
||||
{
|
||||
expr
|
||||
} else {
|
||||
&anon.value
|
||||
};
|
||||
let maybe_res =
|
||||
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
|
||||
debug!("res={:?}", maybe_res);
|
||||
// FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
|
||||
if let Some(res) = maybe_res
|
||||
&& let Res::Def(DefKind::ConstParam, _) = res
|
||||
&& let ExprKind::Path(qself, path) = &expr.kind
|
||||
{
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
return ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Path(qpath),
|
||||
is_desugared_from_effects: false,
|
||||
};
|
||||
}
|
||||
|
||||
let lowered_anon = self.lower_anon_const_to_anon_const(anon);
|
||||
ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Anon(lowered_anon),
|
||||
is_desugared_from_effects: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`hir::ConstArg`] for when to use this function vs
|
||||
/// [`Self::lower_anon_const_to_const_arg`].
|
||||
fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
|
||||
if c.value.is_potential_trivial_const_arg() {
|
||||
// HACK(min_generic_const_args): see DefCollector::visit_anon_const
|
||||
// Over there, we guess if this is a bare param and only create a def if
|
||||
// we think it's not. However we may can guess wrong (see there for example)
|
||||
// in which case we have to create the def here.
|
||||
self.create_def(
|
||||
self.current_def_id_parent,
|
||||
c.id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
c.value.span,
|
||||
);
|
||||
}
|
||||
|
||||
self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
|
||||
let def_id = this.local_def_id(c.id);
|
||||
let hir_id = this.lower_node_id(c.id);
|
||||
hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(c.value.span, Some(&c.value))
|
||||
}),
|
||||
span: this.lower_span(c.value.span),
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -228,13 +228,53 @@ impl<'hir> PathSegment<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A constant that enters the type system, used for arguments to const generics (e.g. array lengths).
|
||||
///
|
||||
/// These are distinct from [`AnonConst`] as anon consts in the type system are not allowed
|
||||
/// to use any generic parameters, therefore we must represent `N` differently. Additionally
|
||||
/// future designs for supporting generic parameters in const arguments will likely not use
|
||||
/// an anon const based design.
|
||||
///
|
||||
/// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args
|
||||
/// that are [just paths](ConstArgKind::Path) (currently just bare const params)
|
||||
/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3 }`).
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
pub struct ConstArg<'hir> {
|
||||
pub value: &'hir AnonConst,
|
||||
#[stable_hasher(ignore)]
|
||||
pub hir_id: HirId,
|
||||
pub kind: ConstArgKind<'hir>,
|
||||
/// Indicates whether this comes from a `~const` desugaring.
|
||||
pub is_desugared_from_effects: bool,
|
||||
}
|
||||
|
||||
impl<'hir> ConstArg<'hir> {
|
||||
pub fn anon_const_hir_id(&self) -> Option<HirId> {
|
||||
match self.kind {
|
||||
ConstArgKind::Anon(ac) => Some(ac.hir_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
match self.kind {
|
||||
ConstArgKind::Path(path) => path.span(),
|
||||
ConstArgKind::Anon(anon) => anon.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`ConstArg`].
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
pub enum ConstArgKind<'hir> {
|
||||
/// **Note:** Currently this is only used for bare const params
|
||||
/// (`N` where `fn foo<const N: usize>(...)`),
|
||||
/// not paths to any const (`N` where `const N: usize = ...`).
|
||||
///
|
||||
/// However, in the future, we'll be using it for all of those.
|
||||
Path(QPath<'hir>),
|
||||
Anon(&'hir AnonConst),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
pub struct InferArg {
|
||||
pub hir_id: HirId,
|
||||
|
@ -251,7 +291,7 @@ impl InferArg {
|
|||
pub enum GenericArg<'hir> {
|
||||
Lifetime(&'hir Lifetime),
|
||||
Type(&'hir Ty<'hir>),
|
||||
Const(ConstArg<'hir>),
|
||||
Const(&'hir ConstArg<'hir>),
|
||||
Infer(InferArg),
|
||||
}
|
||||
|
||||
|
@ -260,7 +300,7 @@ impl GenericArg<'_> {
|
|||
match self {
|
||||
GenericArg::Lifetime(l) => l.ident.span,
|
||||
GenericArg::Type(t) => t.span,
|
||||
GenericArg::Const(c) => c.value.span,
|
||||
GenericArg::Const(c) => c.span(),
|
||||
GenericArg::Infer(i) => i.span,
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +309,7 @@ impl GenericArg<'_> {
|
|||
match self {
|
||||
GenericArg::Lifetime(l) => l.hir_id,
|
||||
GenericArg::Type(t) => t.hir_id,
|
||||
GenericArg::Const(c) => c.value.hir_id,
|
||||
GenericArg::Const(c) => c.hir_id,
|
||||
GenericArg::Infer(i) => i.hir_id,
|
||||
}
|
||||
}
|
||||
|
@ -524,7 +564,7 @@ pub enum GenericParamKind<'hir> {
|
|||
Const {
|
||||
ty: &'hir Ty<'hir>,
|
||||
/// Optional default value for the const generic param
|
||||
default: Option<&'hir AnonConst>,
|
||||
default: Option<&'hir ConstArg<'hir>>,
|
||||
is_host_effect: bool,
|
||||
synthetic: bool,
|
||||
},
|
||||
|
@ -1598,13 +1638,13 @@ pub type Lit = Spanned<LitKind>;
|
|||
#[derive(Copy, Clone, Debug, HashStable_Generic)]
|
||||
pub enum ArrayLen<'hir> {
|
||||
Infer(InferArg),
|
||||
Body(&'hir AnonConst),
|
||||
Body(&'hir ConstArg<'hir>),
|
||||
}
|
||||
|
||||
impl ArrayLen<'_> {
|
||||
pub fn hir_id(&self) -> HirId {
|
||||
match self {
|
||||
ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => {
|
||||
ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(ConstArg { hir_id, .. }) => {
|
||||
*hir_id
|
||||
}
|
||||
}
|
||||
|
@ -2434,7 +2474,7 @@ impl<'hir> AssocItemConstraint<'hir> {
|
|||
}
|
||||
|
||||
/// Obtain the const on the RHS of an assoc const equality constraint if applicable.
|
||||
pub fn ct(self) -> Option<&'hir AnonConst> {
|
||||
pub fn ct(self) -> Option<&'hir ConstArg<'hir>> {
|
||||
match self.kind {
|
||||
AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct),
|
||||
_ => None,
|
||||
|
@ -2445,7 +2485,7 @@ impl<'hir> AssocItemConstraint<'hir> {
|
|||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum Term<'hir> {
|
||||
Ty(&'hir Ty<'hir>),
|
||||
Const(&'hir AnonConst),
|
||||
Const(&'hir ConstArg<'hir>),
|
||||
}
|
||||
|
||||
impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
|
||||
|
@ -2454,8 +2494,8 @@ impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'hir> From<&'hir AnonConst> for Term<'hir> {
|
||||
fn from(c: &'hir AnonConst) -> Self {
|
||||
impl<'hir> From<&'hir ConstArg<'hir>> for Term<'hir> {
|
||||
fn from(c: &'hir ConstArg<'hir>) -> Self {
|
||||
Term::Const(c)
|
||||
}
|
||||
}
|
||||
|
@ -3689,6 +3729,7 @@ pub enum Node<'hir> {
|
|||
Field(&'hir FieldDef<'hir>),
|
||||
AnonConst(&'hir AnonConst),
|
||||
ConstBlock(&'hir ConstBlock),
|
||||
ConstArg(&'hir ConstArg<'hir>),
|
||||
Expr(&'hir Expr<'hir>),
|
||||
ExprField(&'hir ExprField<'hir>),
|
||||
Stmt(&'hir Stmt<'hir>),
|
||||
|
@ -3750,6 +3791,7 @@ impl<'hir> Node<'hir> {
|
|||
Node::Param(..)
|
||||
| Node::AnonConst(..)
|
||||
| Node::ConstBlock(..)
|
||||
| Node::ConstArg(..)
|
||||
| Node::Expr(..)
|
||||
| Node::Stmt(..)
|
||||
| Node::Block(..)
|
||||
|
@ -3966,7 +4008,7 @@ mod size_asserts {
|
|||
static_assert_size!(FnDecl<'_>, 40);
|
||||
static_assert_size!(ForeignItem<'_>, 72);
|
||||
static_assert_size!(ForeignItemKind<'_>, 40);
|
||||
static_assert_size!(GenericArg<'_>, 24);
|
||||
static_assert_size!(GenericArg<'_>, 16);
|
||||
static_assert_size!(GenericBound<'_>, 48);
|
||||
static_assert_size!(Generics<'_>, 56);
|
||||
static_assert_size!(Impl<'_>, 80);
|
||||
|
|
|
@ -347,6 +347,9 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
|
||||
walk_inline_const(self, c)
|
||||
}
|
||||
fn visit_const_arg(&mut self, c: &'v ConstArg<'v>) -> Self::Result {
|
||||
walk_const_arg(self, c)
|
||||
}
|
||||
fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
|
||||
walk_expr(self, ex)
|
||||
}
|
||||
|
@ -364,7 +367,7 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
|
||||
walk_generic_param(self, p)
|
||||
}
|
||||
fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) -> Self::Result {
|
||||
fn visit_const_param_default(&mut self, _param: HirId, ct: &'v ConstArg<'v>) -> Self::Result {
|
||||
walk_const_param_default(self, ct)
|
||||
}
|
||||
fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result {
|
||||
|
@ -708,7 +711,7 @@ pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>
|
|||
match len {
|
||||
// FIXME: Use `visit_infer` here.
|
||||
ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
|
||||
ArrayLen::Body(c) => visitor.visit_anon_const(c),
|
||||
ArrayLen::Body(c) => visitor.visit_const_arg(c),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,6 +728,17 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>(
|
|||
visitor.visit_nested_body(constant.body)
|
||||
}
|
||||
|
||||
pub fn walk_const_arg<'v, V: Visitor<'v>>(
|
||||
visitor: &mut V,
|
||||
const_arg: &'v ConstArg<'v>,
|
||||
) -> V::Result {
|
||||
try_visit!(visitor.visit_id(const_arg.hir_id));
|
||||
match &const_arg.kind {
|
||||
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
|
||||
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
|
||||
try_visit!(visitor.visit_id(expression.hir_id));
|
||||
match expression.kind {
|
||||
|
@ -928,9 +942,9 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
|
|||
|
||||
pub fn walk_const_param_default<'v, V: Visitor<'v>>(
|
||||
visitor: &mut V,
|
||||
ct: &'v AnonConst,
|
||||
ct: &'v ConstArg<'v>,
|
||||
) -> V::Result {
|
||||
visitor.visit_anon_const(ct)
|
||||
visitor.visit_const_arg(ct)
|
||||
}
|
||||
|
||||
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
|
||||
|
@ -1216,7 +1230,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(
|
|||
match generic_arg {
|
||||
GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
|
||||
GenericArg::Type(ty) => visitor.visit_ty(ty),
|
||||
GenericArg::Const(ct) => visitor.visit_anon_const(&ct.value),
|
||||
GenericArg::Const(ct) => visitor.visit_const_arg(ct),
|
||||
GenericArg::Infer(inf) => visitor.visit_infer(inf),
|
||||
}
|
||||
}
|
||||
|
@ -1278,7 +1292,7 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
|
|||
match constraint.kind {
|
||||
AssocItemConstraintKind::Equality { ref term } => match term {
|
||||
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)),
|
||||
Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)),
|
||||
},
|
||||
AssocItemConstraintKind::Bound { bounds } => {
|
||||
walk_list!(visitor, visit_param_bound, bounds)
|
||||
|
|
|
@ -304,7 +304,9 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
|||
self.tcx.ensure().type_of(param.def_id);
|
||||
if let Some(default) = default {
|
||||
// need to store default and type of default
|
||||
self.tcx.ensure().type_of(default.def_id);
|
||||
if let hir::ConstArgKind::Anon(ac) = default.kind {
|
||||
self.tcx.ensure().type_of(ac.def_id);
|
||||
}
|
||||
self.tcx.ensure().const_param_default(param.def_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_session::lint;
|
|||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
use rustc_hir::*;
|
||||
|
||||
|
@ -102,6 +102,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
None
|
||||
} else if tcx.features().generic_const_exprs {
|
||||
let parent_node = tcx.parent_hir_node(hir_id);
|
||||
debug!(?parent_node);
|
||||
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
|
||||
&& constant.hir_id == hir_id
|
||||
{
|
||||
|
@ -164,13 +165,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
}
|
||||
} else {
|
||||
let parent_node = tcx.parent_hir_node(hir_id);
|
||||
let parent_node = match parent_node {
|
||||
Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
|
||||
_ => parent_node,
|
||||
};
|
||||
match parent_node {
|
||||
// HACK(eddyb) this provides the correct generics for repeat
|
||||
// expressions' count (i.e. `N` in `[x; N]`), and explicit
|
||||
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
|
||||
// as they shouldn't be able to cause query cycle errors.
|
||||
Node::Expr(Expr { kind: ExprKind::Repeat(_, constant), .. })
|
||||
if constant.hir_id() == hir_id =>
|
||||
Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. })
|
||||
if ct.anon_const_hir_id() == Some(hir_id) =>
|
||||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
|
|
|
@ -388,7 +388,7 @@ fn const_evaluatable_predicates_of(
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
|
||||
fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
|
||||
// Do not look into const param defaults,
|
||||
// these get checked when they are actually instantiated.
|
||||
//
|
||||
|
|
|
@ -954,7 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
GenericParamKind::Const { ty, default, .. } => {
|
||||
self.visit_ty(ty);
|
||||
if let Some(default) = default {
|
||||
self.visit_body(self.tcx.hir().body(default.body));
|
||||
self.visit_const_arg(default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1594,7 +1594,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
i += 1;
|
||||
}
|
||||
GenericArg::Const(ct) => {
|
||||
self.visit_anon_const(&ct.value);
|
||||
self.visit_const_arg(ct);
|
||||
i += 1;
|
||||
}
|
||||
GenericArg::Infer(inf) => {
|
||||
|
|
|
@ -35,16 +35,32 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
let parent_node_id = tcx.parent_hir_id(hir_id);
|
||||
let parent_node = tcx.hir_node(parent_node_id);
|
||||
|
||||
let (generics, arg_idx) = match parent_node {
|
||||
// Easy case: arrays repeat expressions.
|
||||
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
|
||||
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||
if constant.hir_id() == hir_id =>
|
||||
match parent_node {
|
||||
// Anon consts "inside" the type system.
|
||||
Node::ConstArg(&ConstArg {
|
||||
hir_id: arg_hir_id,
|
||||
kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }),
|
||||
..
|
||||
}) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span),
|
||||
|
||||
// Anon consts outside the type system.
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
|
||||
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const }
|
||||
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
|
||||
_ => false,
|
||||
}) =>
|
||||
{
|
||||
return tcx.types.usize;
|
||||
tcx.typeck(def_id).node_type(hir_id)
|
||||
}
|
||||
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
|
||||
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
|
||||
}
|
||||
// Sort of affects the type system, but only for the purpose of diagnostics
|
||||
// so no need for ConstArg.
|
||||
Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => {
|
||||
let ty = tcx.typeck(def_id).node_type(e.hir_id);
|
||||
let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id));
|
||||
let ty = tcx.fold_regions(ty, |r, _| {
|
||||
if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r }
|
||||
});
|
||||
|
@ -56,24 +72,35 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
|
||||
return ty;
|
||||
}
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
|
||||
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const }
|
||||
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
|
||||
_ => false,
|
||||
}) =>
|
||||
|
||||
_ => Ty::new_error_with_message(
|
||||
tcx,
|
||||
span,
|
||||
format!("unexpected anon const parent in type_of(): {parent_node:?}"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
|
||||
use hir::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
|
||||
let parent_node_id = tcx.parent_hir_id(arg_hir_id);
|
||||
let parent_node = tcx.hir_node(parent_node_id);
|
||||
|
||||
let (generics, arg_idx) = match parent_node {
|
||||
// Easy case: arrays repeat expressions.
|
||||
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
|
||||
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||
if constant.hir_id() == arg_hir_id =>
|
||||
{
|
||||
return tcx.typeck(def_id).node_type(hir_id);
|
||||
}
|
||||
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
|
||||
return tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx);
|
||||
return tcx.types.usize;
|
||||
}
|
||||
Node::GenericParam(&GenericParam {
|
||||
def_id: param_def_id,
|
||||
kind: GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) if ct.hir_id == hir_id => {
|
||||
}) if ct.hir_id == arg_hir_id => {
|
||||
return tcx
|
||||
.type_of(param_def_id)
|
||||
.no_bound_vars()
|
||||
|
@ -104,7 +131,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
// to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
|
||||
let item_def_id = tcx
|
||||
.hir()
|
||||
.parent_owner_iter(hir_id)
|
||||
.parent_owner_iter(arg_hir_id)
|
||||
.find(|(_, node)| matches!(node, OwnerNode::Item(_)))
|
||||
.unwrap()
|
||||
.0
|
||||
|
@ -124,7 +151,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
args.args
|
||||
.iter()
|
||||
.filter(|arg| arg.is_ty_or_const())
|
||||
.position(|arg| arg.hir_id() == hir_id)
|
||||
.position(|arg| arg.hir_id() == arg_hir_id)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
bug!("no arg matching AnonConst in segment");
|
||||
|
@ -145,7 +172,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
|
||||
..
|
||||
}) => {
|
||||
let body_owner = tcx.hir().enclosing_body_owner(hir_id);
|
||||
let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
|
||||
let tables = tcx.typeck(body_owner);
|
||||
// This may fail in case the method/path does not actually exist.
|
||||
// As there is no relevant param for `def_id`, we simply return
|
||||
|
@ -163,10 +190,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
args.args
|
||||
.iter()
|
||||
.filter(|arg| arg.is_ty_or_const())
|
||||
.position(|arg| arg.hir_id() == hir_id)
|
||||
.position(|arg| arg.hir_id() == arg_hir_id)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
bug!("no arg matching AnonConst in segment");
|
||||
bug!("no arg matching ConstArg in segment");
|
||||
});
|
||||
|
||||
(tcx.generics_of(type_dependent_def), idx)
|
||||
|
@ -185,18 +212,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
| ExprKind::Struct(&QPath::Resolved(_, path), ..),
|
||||
..
|
||||
}) => {
|
||||
let body_owner = tcx.hir().enclosing_body_owner(hir_id);
|
||||
let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
|
||||
let _tables = tcx.typeck(body_owner);
|
||||
&*path
|
||||
}
|
||||
Node::Pat(pat) => {
|
||||
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
|
||||
if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) {
|
||||
path
|
||||
} else {
|
||||
return Ty::new_error_with_message(
|
||||
tcx,
|
||||
span,
|
||||
format!("unable to find const parent for {hir_id} in pat {pat:?}"),
|
||||
format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -217,14 +244,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
args.args
|
||||
.iter()
|
||||
.filter(|arg| arg.is_ty_or_const())
|
||||
.position(|arg| arg.hir_id() == hir_id)
|
||||
.position(|arg| arg.hir_id() == arg_hir_id)
|
||||
.map(|index| (index, seg))
|
||||
.or_else(|| {
|
||||
args.constraints
|
||||
.iter()
|
||||
.copied()
|
||||
.filter_map(AssocItemConstraint::ct)
|
||||
.position(|ct| ct.hir_id == hir_id)
|
||||
.position(|ct| ct.hir_id == arg_hir_id)
|
||||
.map(|idx| (idx, seg))
|
||||
})
|
||||
}) else {
|
||||
|
@ -249,7 +276,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
|
|||
return Ty::new_error_with_message(
|
||||
tcx,
|
||||
span,
|
||||
format!("unexpected const parent in type_of(): {parent_node:?}"),
|
||||
format!("unexpected const arg parent in type_of(): {parent_node:?}"),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -413,12 +413,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
});
|
||||
|
||||
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
|
||||
if let Some(anon_const) = constraint.ct() {
|
||||
let ty = alias_term
|
||||
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
|
||||
let ty =
|
||||
check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
|
||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||
if let Some(const_arg) = constraint.ct() {
|
||||
if let hir::ConstArgKind::Anon(anon_const) = const_arg.kind {
|
||||
let ty = alias_term
|
||||
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
|
||||
let ty = check_assoc_const_binding_type(
|
||||
self,
|
||||
constraint.ident,
|
||||
ty,
|
||||
constraint.hir_id,
|
||||
);
|
||||
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
|
||||
}
|
||||
}
|
||||
|
||||
alias_term
|
||||
|
@ -435,7 +441,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
hir::AssocItemConstraintKind::Equality { term } => {
|
||||
let term = match term {
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(),
|
||||
hir::Term::Const(ct) => {
|
||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
|
||||
}
|
||||
};
|
||||
|
||||
// Find any late-bound regions declared in `ty` that are not
|
||||
|
|
|
@ -340,7 +340,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
{
|
||||
let span = match term {
|
||||
hir::Term::Ty(ty) => ty.span,
|
||||
hir::Term::Const(ct) => tcx.def_span(ct.def_id),
|
||||
hir::Term::Const(ct) => ct.span(),
|
||||
};
|
||||
(span, Some(ident.span), assoc_item.kind, assoc_kind)
|
||||
} else {
|
||||
|
@ -1294,8 +1294,7 @@ pub fn prohibit_assoc_item_constraint(
|
|||
hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => {
|
||||
let span = tcx.hir().span(c.hir_id);
|
||||
suggest_direct_use(&mut err, span);
|
||||
suggest_direct_use(&mut err, c.span());
|
||||
}
|
||||
(hir::AssocItemConstraintKind::Bound { bounds }, _) => {
|
||||
// Suggest `impl<T: Bound> Trait<T> for Foo` when finding
|
||||
|
|
|
@ -113,8 +113,12 @@ fn generic_arg_mismatch_err(
|
|||
}
|
||||
}
|
||||
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
|
||||
let body = tcx.hir().body(cnst.value.body);
|
||||
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
|
||||
// FIXME(min_generic_const_args): once ConstArgKind::Path is used for non-params too,
|
||||
// this should match against that instead of ::Anon
|
||||
if let hir::ConstArgKind::Anon(anon) = cnst.kind
|
||||
&& let body = tcx.hir().body(anon.body)
|
||||
&& let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
|
||||
body.value.kind
|
||||
{
|
||||
if let Res::Def(DefKind::Fn { .. }, id) = path.res {
|
||||
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
|
||||
|
|
|
@ -471,11 +471,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
handle_ty_args(has_default, &inf.to_ty())
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
let did = ct.value.def_id;
|
||||
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
|
||||
ty::Const::from_anon_const(tcx, did).into()
|
||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
|
||||
.into()
|
||||
}
|
||||
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
|
||||
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||
self.lowerer.ct_infer(Some(param), inf.span).into()
|
||||
}
|
||||
(kind, arg) => span_bug!(
|
||||
|
@ -912,7 +911,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let term: ty::Term<'_> = match term {
|
||||
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
|
||||
hir::Term::Const(ct) => {
|
||||
ty::Const::from_anon_const(tcx, ct.def_id).into()
|
||||
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
|
||||
.into()
|
||||
}
|
||||
};
|
||||
// FIXME(#97583): This isn't syntactically well-formed!
|
||||
|
@ -2140,7 +2140,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let length = match length {
|
||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||
hir::ArrayLen::Body(constant) => {
|
||||
ty::Const::from_anon_const(tcx, constant.def_id)
|
||||
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,8 +12,9 @@ use rustc_ast_pretty::pp::{self, Breaks};
|
|||
use rustc_ast_pretty::pprust::{Comments, PrintState};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{
|
||||
BindingMode, ByRef, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId,
|
||||
LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TraitBoundModifier,
|
||||
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
|
||||
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
|
||||
TraitBoundModifier,
|
||||
};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
|
@ -87,6 +88,7 @@ impl<'a> State<'a> {
|
|||
Node::Variant(a) => self.print_variant(a),
|
||||
Node::AnonConst(a) => self.print_anon_const(a),
|
||||
Node::ConstBlock(a) => self.print_inline_const(a),
|
||||
Node::ConstArg(a) => self.print_const_arg(a),
|
||||
Node::Expr(a) => self.print_expr(a),
|
||||
Node::ExprField(a) => self.print_expr_field(a),
|
||||
Node::Stmt(a) => self.print_stmt(a),
|
||||
|
@ -983,7 +985,7 @@ impl<'a> State<'a> {
|
|||
fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) {
|
||||
match len {
|
||||
hir::ArrayLen::Infer(..) => self.word("_"),
|
||||
hir::ArrayLen::Body(ct) => self.print_anon_const(ct),
|
||||
hir::ArrayLen::Body(ct) => self.print_const_arg(ct),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -991,6 +993,13 @@ impl<'a> State<'a> {
|
|||
self.ann.nested(self, Nested::Body(constant.body))
|
||||
}
|
||||
|
||||
fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
|
||||
match &const_arg.kind {
|
||||
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
|
||||
ConstArgKind::Anon(anon) => self.print_anon_const(anon),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_call_post(&mut self, args: &[hir::Expr<'_>]) {
|
||||
self.popen();
|
||||
self.commasep_exprs(Inconsistent, args);
|
||||
|
@ -1679,7 +1688,7 @@ impl<'a> State<'a> {
|
|||
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
|
||||
GenericArg::Lifetime(_) => {}
|
||||
GenericArg::Type(ty) => s.print_type(ty),
|
||||
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
|
||||
GenericArg::Const(ct) => s.print_const_arg(ct),
|
||||
GenericArg::Infer(_inf) => s.word("_"),
|
||||
}
|
||||
});
|
||||
|
@ -1720,7 +1729,7 @@ impl<'a> State<'a> {
|
|||
self.word_space("=");
|
||||
match term {
|
||||
Term::Ty(ty) => self.print_type(ty),
|
||||
Term::Const(ref c) => self.print_anon_const(c),
|
||||
Term::Const(ref c) => self.print_const_arg(c),
|
||||
}
|
||||
}
|
||||
hir::AssocItemConstraintKind::Bound { bounds } => {
|
||||
|
@ -2155,7 +2164,7 @@ impl<'a> State<'a> {
|
|||
if let Some(default) = default {
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
self.print_anon_const(default);
|
||||
self.print_const_arg(default);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1439,9 +1439,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
|
||||
&& let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length
|
||||
&& let hir::ArrayLen::Body(ct) = length
|
||||
{
|
||||
let span = self.tcx.hir().span(hir_id);
|
||||
let span = ct.span();
|
||||
self.dcx().try_steal_modify_and_emit_err(
|
||||
span,
|
||||
StashKey::UnderscoreForArrayLengths,
|
||||
|
|
|
@ -457,22 +457,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
|
||||
match length {
|
||||
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
|
||||
hir::ArrayLen::Body(anon_const) => {
|
||||
let span = self.tcx.def_span(anon_const.def_id);
|
||||
let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id);
|
||||
hir::ArrayLen::Body(const_arg) => {
|
||||
let span = const_arg.span();
|
||||
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
|
||||
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
|
||||
self.normalize(span, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_const_arg(&self, hir_ct: &hir::AnonConst, param_def_id: DefId) -> ty::Const<'tcx> {
|
||||
let did = hir_ct.def_id;
|
||||
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
|
||||
let ct = ty::Const::from_anon_const(self.tcx, did);
|
||||
pub fn lower_const_arg(
|
||||
&self,
|
||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||
param_def_id: DefId,
|
||||
) -> ty::Const<'tcx> {
|
||||
let ct =
|
||||
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
|
||||
self.register_wf_obligation(
|
||||
ct.into(),
|
||||
self.tcx.hir().span(hir_ct.hir_id),
|
||||
self.tcx.hir().span(const_arg.hir_id),
|
||||
ObligationCauseCode::WellFormed(None),
|
||||
);
|
||||
ct
|
||||
|
@ -1298,7 +1301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.fcx.lower_ty(ty).raw.into()
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
self.fcx.lower_const_arg(&ct.value, param.def_id).into()
|
||||
self.fcx.lower_const_arg(ct, param.def_id).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||
self.fcx.ty_infer(Some(param), inf.span).into()
|
||||
|
|
|
@ -400,7 +400,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
self.cfcx.lower_ty(ty).raw.into()
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||
self.cfcx.lower_const_arg(&ct.value, param.def_id).into()
|
||||
self.cfcx.lower_const_arg(ct, param.def_id).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
|
||||
self.cfcx.ty_infer(Some(param), inf.span).into()
|
||||
|
|
|
@ -1762,9 +1762,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
if let Some(tykind) = tykind
|
||||
&& let hir::TyKind::Array(_, length) = tykind
|
||||
&& let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
|
||||
&& let hir::ArrayLen::Body(ct) = length
|
||||
{
|
||||
let span = self.tcx.hir().span(*hir_id);
|
||||
let span = ct.span();
|
||||
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
|
|||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_snippet(c.value.span)
|
||||
.span_to_snippet(c.span())
|
||||
.unwrap_or_else(|_| "_".into()),
|
||||
GenericArg::Infer(_) => String::from("_"),
|
||||
})
|
||||
|
|
|
@ -912,6 +912,7 @@ impl<'hir> Map<'hir> {
|
|||
Node::Field(field) => field.span,
|
||||
Node::AnonConst(constant) => constant.span,
|
||||
Node::ConstBlock(constant) => self.body(constant.body).value.span,
|
||||
Node::ConstArg(const_arg) => const_arg.span(),
|
||||
Node::Expr(expr) => expr.span,
|
||||
Node::ExprField(field) => field.span,
|
||||
Node::Stmt(stmt) => stmt.span,
|
||||
|
@ -962,7 +963,8 @@ impl<'hir> Map<'hir> {
|
|||
/// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
|
||||
/// called with the HirId for the `{ ... }` anon const
|
||||
pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
|
||||
match self.tcx.parent_hir_node(anon_const) {
|
||||
let const_arg = self.tcx.parent_hir_id(anon_const);
|
||||
match self.tcx.parent_hir_node(const_arg) {
|
||||
Node::GenericParam(GenericParam {
|
||||
def_id: param_id,
|
||||
kind: GenericParamKind::Const { .. },
|
||||
|
@ -1182,6 +1184,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
}
|
||||
Node::AnonConst(_) => node_str("const"),
|
||||
Node::ConstBlock(_) => node_str("const"),
|
||||
Node::ConstArg(_) => node_str("const"),
|
||||
Node::Expr(_) => node_str("expr"),
|
||||
Node::ExprField(_) => node_str("expr field"),
|
||||
Node::Stmt(_) => node_str("stmt"),
|
||||
|
|
|
@ -4,9 +4,9 @@ use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisita
|
|||
use either::Either;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::MultiSpan;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||
use tracing::{debug, instrument};
|
||||
|
@ -183,16 +183,55 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
||||
/// through const generics need to have their type "fed" to them
|
||||
/// using the query system.
|
||||
///
|
||||
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
|
||||
/// desired behavior.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FeedConstTy {
|
||||
/// Feed the type.
|
||||
///
|
||||
/// The `DefId` belongs to the const param that we are supplying
|
||||
/// this (anon) const arg to.
|
||||
Param(DefId),
|
||||
/// Don't feed the type.
|
||||
No,
|
||||
}
|
||||
|
||||
impl<'tcx> Const<'tcx> {
|
||||
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn from_const_arg(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||
feed: FeedConstTy,
|
||||
) -> Self {
|
||||
if let FeedConstTy::Param(param_def_id) = feed
|
||||
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||
{
|
||||
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||
}
|
||||
|
||||
match const_arg.kind {
|
||||
hir::ConstArgKind::Path(qpath) => {
|
||||
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
|
||||
Self::from_param(tcx, qpath, const_arg.hir_id)
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||
/// becomes `Unevaluated`.
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
|
||||
let body_id = match tcx.hir_node_by_def_id(def) {
|
||||
hir::Node::AnonConst(ac) => ac.body,
|
||||
_ => span_bug!(
|
||||
node => span_bug!(
|
||||
tcx.def_span(def.to_def_id()),
|
||||
"from_anon_const can only process anonymous constants"
|
||||
"from_anon_const can only process anonymous constants, not {node:?}"
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -201,7 +240,7 @@ impl<'tcx> Const<'tcx> {
|
|||
|
||||
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
||||
|
||||
match Self::try_from_lit_or_param(tcx, ty, expr) {
|
||||
match Self::try_from_lit(tcx, ty, expr) {
|
||||
Some(v) => v,
|
||||
None => ty::Const::new_unevaluated(
|
||||
tcx,
|
||||
|
@ -213,12 +252,36 @@ impl<'tcx> Const<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Lower a const param to a [`Const`].
|
||||
///
|
||||
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
|
||||
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
|
||||
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
|
||||
qpath
|
||||
else {
|
||||
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
|
||||
};
|
||||
|
||||
match tcx.named_bound_var(hir_id) {
|
||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||
// Find the name and index of the const parameter by indexing the generics of
|
||||
// the parent item and construct a `ParamConst`.
|
||||
let item_def_id = tcx.parent(def_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.param_def_id_to_index[&def_id];
|
||||
let name = tcx.item_name(def_id);
|
||||
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
||||
}
|
||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
||||
}
|
||||
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
fn try_from_lit_or_param(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Option<Self> {
|
||||
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
|
||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = match &expr.kind {
|
||||
|
@ -251,34 +314,15 @@ impl<'tcx> Const<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
|
||||
// does not provide the parents generics to anonymous constants. We still allow generic const
|
||||
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
|
||||
// ever try to instantiate the generic parameters in their bodies.
|
||||
match expr.kind {
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
|
||||
)) => {
|
||||
match tcx.named_bound_var(expr.hir_id) {
|
||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||
// Find the name and index of the const parameter by indexing the generics of
|
||||
// the parent item and construct a `ParamConst`.
|
||||
let item_def_id = tcx.parent(def_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.param_def_id_to_index[&def_id];
|
||||
let name = tcx.item_name(def_id);
|
||||
Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
|
||||
}
|
||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||
Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
|
||||
}
|
||||
Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
|
||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
if let hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
|
||||
)) = expr.kind
|
||||
{
|
||||
span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -483,15 +527,15 @@ pub fn const_param_default<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||
let default_def_id = match tcx.hir_node_by_def_id(def_id) {
|
||||
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { default: Some(ac), .. },
|
||||
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) => ac.def_id,
|
||||
}) => ct,
|
||||
_ => span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"`const_param_default` expected a generic parameter with a constant"
|
||||
),
|
||||
};
|
||||
ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
|
||||
ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ pub use self::closure::{
|
|||
CAPTURE_STRUCT_LOCAL,
|
||||
};
|
||||
pub use self::consts::{
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
||||
|
|
|
@ -607,7 +607,9 @@ impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
|
|||
type Output = V;
|
||||
|
||||
fn index(&self, key: HirId) -> &V {
|
||||
self.get(key).expect("LocalTableInContext: key not found")
|
||||
self.get(key).unwrap_or_else(|| {
|
||||
bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -452,7 +452,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
match ga {
|
||||
hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||
hir::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
hir::GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
|
||||
hir::GenericArg::Const(ct) => self.visit_const_arg(ct),
|
||||
hir::GenericArg::Infer(inf) => self.visit_infer(inf),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,8 +312,19 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
|
||||
let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
|
||||
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
|
||||
// HACK(min_generic_const_args): don't create defs for anon consts if we think they will
|
||||
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
|
||||
// may accidentally identify a construction of a unit struct as a param and not create a
|
||||
// def. we'll then create a def later in ast lowering in this case. the parent of nested
|
||||
// items will be messed up, but that's ok because there can't be any if we're just looking
|
||||
// for bare idents.
|
||||
if constant.value.is_potential_trivial_const_arg() {
|
||||
visit::walk_anon_const(self, constant)
|
||||
} else {
|
||||
let def =
|
||||
self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
|
||||
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||
|
|
|
@ -672,9 +672,21 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
|
||||
}
|
||||
|
||||
ty::Array(subty, _) => {
|
||||
ty::Array(subty, len) => {
|
||||
self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
|
||||
// Note that we handle the len is implicitly checked while walking `arg`.
|
||||
// Note that the len being WF is implicitly checked while visiting.
|
||||
// Here we just check that it's of type usize.
|
||||
let cause = self.cause(ObligationCauseCode::Misc);
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
tcx,
|
||||
cause,
|
||||
self.recursion_depth,
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
|
||||
len,
|
||||
tcx.types.usize,
|
||||
))),
|
||||
));
|
||||
}
|
||||
|
||||
ty::Pat(subty, _) => {
|
||||
|
|
|
@ -285,10 +285,17 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
|
|||
}
|
||||
|
||||
pub(crate) fn clean_const<'tcx>(
|
||||
constant: &hir::ConstArg<'_>,
|
||||
constant: &hir::ConstArg<'tcx>,
|
||||
_cx: &mut DocContext<'tcx>,
|
||||
) -> Constant {
|
||||
Constant { kind: ConstantKind::Anonymous { body: constant.value.body } }
|
||||
match &constant.kind {
|
||||
hir::ConstArgKind::Path(qpath) => {
|
||||
Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } }
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => {
|
||||
Constant { kind: ConstantKind::Anonymous { body: anon.body } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clean_middle_const<'tcx>(
|
||||
|
@ -431,7 +438,7 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
|
|||
match term {
|
||||
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
|
||||
hir::Term::Const(c) => Term::Constant(clean_middle_const(
|
||||
ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, c.def_id)),
|
||||
ty::Binder::dummy(ty::Const::from_const_arg(cx.tcx, c, ty::FeedConstTy::No)),
|
||||
cx,
|
||||
)),
|
||||
}
|
||||
|
@ -633,8 +640,9 @@ fn clean_generic_param<'tcx>(
|
|||
param.name.ident().name,
|
||||
GenericParamDefKind::Const {
|
||||
ty: Box::new(clean_ty(ty, cx)),
|
||||
default: default
|
||||
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
|
||||
default: default.map(|ct| {
|
||||
Box::new(ty::Const::from_const_arg(cx.tcx, ct, ty::FeedConstTy::No).to_string())
|
||||
}),
|
||||
synthetic,
|
||||
},
|
||||
),
|
||||
|
@ -1820,7 +1828,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||
TyKind::Array(ty, ref length) => {
|
||||
let length = match length {
|
||||
hir::ArrayLen::Infer(..) => "_".to_string(),
|
||||
hir::ArrayLen::Body(anon_const) => {
|
||||
hir::ArrayLen::Body(const_arg) => {
|
||||
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
|
||||
// as we currently do not supply the parent generics to anonymous constants
|
||||
// but do allow `ConstKind::Param`.
|
||||
|
@ -1828,9 +1836,18 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
|
|||
// `const_eval_poly` tries to first substitute generic parameters which
|
||||
// results in an ICE while manually constructing the constant and using `eval`
|
||||
// does nothing for `ConstKind::Param`.
|
||||
let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id);
|
||||
let param_env = cx.tcx.param_env(anon_const.def_id);
|
||||
print_const(cx, ct.normalize(cx.tcx, param_env))
|
||||
let ct = ty::Const::from_const_arg(cx.tcx, const_arg, ty::FeedConstTy::No);
|
||||
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
|
||||
const_arg.kind
|
||||
{
|
||||
// Only anon consts can implicitly capture params.
|
||||
// FIXME: is this correct behavior?
|
||||
let param_env = cx.tcx.param_env(*def_id);
|
||||
ct.normalize(cx.tcx, param_env)
|
||||
} else {
|
||||
ct
|
||||
};
|
||||
print_const(cx, ct)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2395,6 +2395,9 @@ pub(crate) enum ConstantKind {
|
|||
/// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified
|
||||
/// by a DefId. So this field must be different from `Extern`.
|
||||
TyConst { expr: Box<str> },
|
||||
/// A constant that is just a path (i.e., referring to a const param, free const, etc.).
|
||||
// FIXME: this is an unfortunate representation. rustdoc's logic around consts needs to be improved.
|
||||
Path { path: Box<str> },
|
||||
/// A constant (expression) that's not an item or associated item. These are usually found
|
||||
/// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
|
||||
/// used to define explicit discriminant values for enum variants.
|
||||
|
@ -2423,6 +2426,7 @@ impl ConstantKind {
|
|||
pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> String {
|
||||
match *self {
|
||||
ConstantKind::TyConst { ref expr } => expr.to_string(),
|
||||
ConstantKind::Path { ref path } => path.to_string(),
|
||||
ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id),
|
||||
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
|
||||
rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body))
|
||||
|
@ -2432,7 +2436,9 @@ impl ConstantKind {
|
|||
|
||||
pub(crate) fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
|
||||
match *self {
|
||||
ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None,
|
||||
ConstantKind::TyConst { .. }
|
||||
| ConstantKind::Path { .. }
|
||||
| ConstantKind::Anonymous { .. } => None,
|
||||
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
|
||||
print_evaluated_const(tcx, def_id, true, true)
|
||||
}
|
||||
|
@ -2441,7 +2447,9 @@ impl ConstantKind {
|
|||
|
||||
pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
|
||||
match *self {
|
||||
ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } => false,
|
||||
ConstantKind::TyConst { .. }
|
||||
| ConstantKind::Extern { .. }
|
||||
| ConstantKind::Path { .. } => false,
|
||||
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
|
||||
is_literal_expr(tcx, body.hir_id)
|
||||
}
|
||||
|
|
|
@ -106,13 +106,12 @@ fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
|
|||
///
|
||||
/// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
|
||||
/// correct result.
|
||||
fn repeat_expr_might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
|
||||
let ExprKind::Repeat(_, ArrayLen::Body(anon_const)) = expr.kind else {
|
||||
fn repeat_expr_might_be_expanded<'tcx>(expr: &Expr<'tcx>) -> bool {
|
||||
let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
|
||||
return false;
|
||||
};
|
||||
let len_span = cx.tcx.def_span(anon_const.def_id);
|
||||
!expr.span.contains(len_span)
|
||||
!expr.span.contains(len_ct.span())
|
||||
}
|
||||
|
||||
expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(cx, expr)
|
||||
expr.span.from_expansion() || is_from_proc_macro(cx, expr) || repeat_expr_might_be_expanded(expr)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
|
|||
use clippy_utils::has_repr_attr;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::Const;
|
||||
use rustc_middle::ty::{Const, FeedConstTy};
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -53,14 +53,14 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
||||
if let ItemKind::Struct(data, _) = &item.kind
|
||||
// First check if last field is an array
|
||||
&& let Some(last_field) = data.fields().last()
|
||||
&& let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
|
||||
|
||||
// Then check if that array is zero-sized
|
||||
&& let length = Const::from_anon_const(cx.tcx, length.def_id)
|
||||
&& let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No)
|
||||
&& let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||
&& let Some(length) = length
|
||||
{
|
||||
|
|
|
@ -5,10 +5,9 @@ use clippy_utils::{get_attr, higher};
|
|||
use rustc_ast::ast::{LitFloatType, LitKind};
|
||||
use rustc_ast::LitIntType;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{
|
||||
ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind,
|
||||
QPath, StmtKind, TyKind,
|
||||
self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
|
||||
ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
@ -270,6 +269,21 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn const_arg(&self, const_arg: &Binding<&ConstArg<'_>>) {
|
||||
match const_arg.value.kind {
|
||||
ConstArgKind::Path(ref qpath) => {
|
||||
bind!(self, qpath);
|
||||
chain!(self, "let ConstArgKind::Path(ref {qpath}) = {const_arg}.kind");
|
||||
self.qpath(qpath);
|
||||
},
|
||||
ConstArgKind::Anon(anon_const) => {
|
||||
bind!(self, anon_const);
|
||||
chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
|
||||
self.body(field!(anon_const.body));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn lit(&self, lit: &Binding<&Lit>) {
|
||||
let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
|
||||
macro_rules! kind {
|
||||
|
@ -602,10 +616,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||
self.expr(value);
|
||||
match length.value {
|
||||
ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
|
||||
ArrayLen::Body(anon_const) => {
|
||||
bind!(self, anon_const);
|
||||
chain!(self, "let ArrayLen::Body({anon_const}) = {length}");
|
||||
self.body(field!(anon_const.body));
|
||||
ArrayLen::Body(const_arg) => {
|
||||
bind!(self, const_arg);
|
||||
chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
|
||||
self.const_arg(const_arg);
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,9 +7,9 @@ use rustc_data_structures::fx::FxHasher;
|
|||
use rustc_hir::def::Res;
|
||||
use rustc_hir::MatchSource::TryDesugar;
|
||||
use rustc_hir::{
|
||||
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy,
|
||||
GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField,
|
||||
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
|
||||
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
|
||||
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
|
||||
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
|
||||
};
|
||||
use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
@ -227,7 +227,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
|
||||
match (left, right) {
|
||||
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
|
||||
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_body(l_ct.body, r_ct.body),
|
||||
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
|
||||
(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
|
||||
fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
|
||||
match (left, right) {
|
||||
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
|
||||
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r),
|
||||
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
|
||||
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
|
||||
(GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
|
||||
|
@ -419,6 +419,17 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn eq_const_arg(&mut self, left: &ConstArg<'_>, right: &ConstArg<'_>) -> bool {
|
||||
match (&left.kind, &right.kind) {
|
||||
(ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
|
||||
(ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
|
||||
// Use explicit match for now since ConstArg is undergoing flux.
|
||||
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
|
||||
false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
|
||||
left.res == right.res
|
||||
}
|
||||
|
@ -1123,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
|
||||
match length {
|
||||
ArrayLen::Infer(..) => {},
|
||||
ArrayLen::Body(anon_const) => self.hash_body(anon_const.body),
|
||||
ArrayLen::Body(ct) => self.hash_const_arg(ct),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1134,12 +1145,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
self.maybe_typeck_results = old_maybe_typeck_results;
|
||||
}
|
||||
|
||||
fn hash_const_arg(&mut self, const_arg: &ConstArg<'_>) {
|
||||
match &const_arg.kind {
|
||||
ConstArgKind::Path(path) => self.hash_qpath(path),
|
||||
ConstArgKind::Anon(anon) => self.hash_body(anon.body),
|
||||
}
|
||||
}
|
||||
|
||||
fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
|
||||
for arg in arg_list {
|
||||
match *arg {
|
||||
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
||||
GenericArg::Type(ty) => self.hash_ty(ty),
|
||||
GenericArg::Const(ref ca) => self.hash_body(ca.value.body),
|
||||
GenericArg::Const(ref ca) => self.hash_const_arg(ca),
|
||||
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,11 +102,11 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet};
|
|||
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
||||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
||||
use rustc_hir::{
|
||||
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext,
|
||||
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
|
||||
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
|
||||
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
|
||||
TyKind, UnOp,
|
||||
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
|
||||
ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
|
||||
ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
|
||||
Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
|
||||
TraitRef, TyKind, UnOp,
|
||||
};
|
||||
use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
|
@ -904,7 +904,8 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||
},
|
||||
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
|
||||
ExprKind::Repeat(x, ArrayLen::Body(len)) => {
|
||||
if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
|
||||
if let ConstArgKind::Anon(anon_const) = len.kind
|
||||
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
|
||||
&& let LitKind::Int(v, _) = const_lit.node
|
||||
&& v <= 32
|
||||
&& is_default_equivalent(cx, x)
|
||||
|
@ -933,7 +934,8 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
|
|||
}) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
|
||||
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
|
||||
ExprKind::Repeat(_, ArrayLen::Body(len)) => {
|
||||
if let ExprKind::Lit(const_lit) = cx.tcx.hir().body(len.body).value.kind
|
||||
if let ConstArgKind::Anon(anon_const) = len.kind
|
||||
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
|
||||
&& let LitKind::Int(v, _) = const_lit.node
|
||||
{
|
||||
return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
if let ExprKind::Repeat(value, length) = expr.kind
|
||||
&& let ExprKind::Lit(ref lit) = value.kind
|
||||
&& let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
|
||||
&& let ArrayLen::Body(anon_const) = length
|
||||
&& let ArrayLen::Body(const_arg) = length
|
||||
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
|
||||
&& expr1 = &cx.tcx.hir().body(anon_const.body).value
|
||||
&& let ExprKind::Lit(ref lit1) = expr1.kind
|
||||
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node
|
||||
|
|
|
@ -193,5 +193,11 @@ error: this ident consists of a single char
|
|||
LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 {
|
||||
| ^
|
||||
|
||||
error: aborting due to 32 previous errors
|
||||
error: this ident consists of a single char
|
||||
--> tests/ui/min_ident_chars.rs:93:41
|
||||
|
|
||||
LL | struct Array<T, const N: usize>([T; N]);
|
||||
| ^
|
||||
|
||||
error: aborting due to 33 previous errors
|
||||
|
||||
|
|
11
tests/crashes/127009.rs
Normal file
11
tests/crashes/127009.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
//@ known-bug: #127009
|
||||
|
||||
#![feature(non_lifetime_binders)]
|
||||
|
||||
fn b()
|
||||
where
|
||||
for<const C: usize> [(); C]: Copy,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -33,7 +33,7 @@ fn test_stable_mir() -> ControlFlow<()> {
|
|||
// Get all items and split generic vs monomorphic items.
|
||||
let (generic, mono): (Vec<_>, Vec<_>) =
|
||||
items.into_iter().partition(|item| item.requires_monomorphization());
|
||||
assert_eq!(mono.len(), 4, "Expected 2 mono functions and one constant");
|
||||
assert_eq!(mono.len(), 3, "Expected 3 mono functions");
|
||||
assert_eq!(generic.len(), 2, "Expected 2 generic functions");
|
||||
|
||||
// For all monomorphic items, get the correspondent instances.
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
#![feature(with_negative_coherence)]
|
||||
trait Trait {}
|
||||
impl<const N: u8> Trait for [(); N] {}
|
||||
//~^ ERROR: mismatched types
|
||||
impl<const N: i8> Trait for [(); N] {}
|
||||
//~^ ERROR: mismatched types
|
||||
//~| ERROR: conflicting implementations of trait `Trait`
|
||||
//~^ ERROR: conflicting implementations of trait `Trait`
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]`
|
||||
--> $DIR/generic_const_type_mismatch.rs:9:1
|
||||
--> $DIR/generic_const_type_mismatch.rs:8:1
|
||||
|
|
||||
LL | impl<const N: u8> Trait for [(); N] {}
|
||||
| ----------------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl<const N: i8> Trait for [(); N] {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/generic_const_type_mismatch.rs:7:34
|
||||
|
|
||||
LL | impl<const N: u8> Trait for [(); N] {}
|
||||
| ^ expected `usize`, found `u8`
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/generic_const_type_mismatch.rs:9:34
|
||||
|
|
||||
LL | impl<const N: i8> Trait for [(); N] {}
|
||||
| ^ expected `usize`, found `i8`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0119, E0308.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
|
|
@ -6,7 +6,7 @@ trait Q {
|
|||
}
|
||||
|
||||
impl<const N: u64> Q for [u8; N] {
|
||||
//~^ ERROR mismatched types
|
||||
//~^ ERROR: the constant `N` is not of type `usize`
|
||||
const ASSOC: usize = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
error: the constant `N` is not of type `usize`
|
||||
--> $DIR/bad-subst-const-kind.rs:8:26
|
||||
|
|
||||
LL | impl<const N: u64> Q for [u8; N] {
|
||||
| ^^^^^^^ expected `usize`, found `u64`
|
||||
|
||||
error: the constant `13` is not of type `u64`
|
||||
--> $DIR/bad-subst-const-kind.rs:13:24
|
||||
|
|
||||
|
@ -12,12 +18,5 @@ LL | impl<const N: u64> Q for [u8; N] {
|
|||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-subst-const-kind.rs:8:31
|
||||
|
|
||||
LL | impl<const N: u64> Q for [u8; N] {
|
||||
| ^ expected `usize`, found `u64`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -7,7 +7,7 @@ trait Q {
|
|||
|
||||
impl<const N: u64> Q for [u8; N] {}
|
||||
//~^ ERROR not all trait items implemented
|
||||
//~| ERROR mismatched types
|
||||
//~| ERROR the constant `N` is not of type `usize`
|
||||
|
||||
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
|
||||
//~^ ERROR the constant `13` is not of type `u64`
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
error: the constant `N` is not of type `usize`
|
||||
--> $DIR/type_mismatch.rs:8:26
|
||||
|
|
||||
LL | impl<const N: u64> Q for [u8; N] {}
|
||||
| ^^^^^^^ expected `usize`, found `u64`
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `ASSOC`
|
||||
--> $DIR/type_mismatch.rs:8:1
|
||||
|
|
||||
|
@ -29,12 +35,6 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
|
|||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:8:31
|
||||
|
|
||||
LL | impl<const N: u64> Q for [u8; N] {}
|
||||
| ^ expected `usize`, found `u64`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0308.
|
||||
|
|
|
@ -25,8 +25,8 @@ mod v20 {
|
|||
}
|
||||
|
||||
impl<const v10: usize> v17<v10, v2> {
|
||||
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
|
||||
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
|
||||
pub const fn v21() -> v18 {
|
||||
//~^ ERROR cannot find type `v18` in this scope
|
||||
v18 { _p: () }
|
||||
|
|
|
@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
|
|||
LL + #![feature(adt_const_params)]
|
||||
|
|
||||
|
||||
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:27:37
|
||||
|
|
||||
LL | impl<const v10: usize> v17<v10, v2> {
|
||||
| ^^
|
||||
|
||||
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:27:37
|
||||
|
|
||||
LL | impl<const v10: usize> v17<v10, v2> {
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
--> $DIR/issue-88119.rs:21:5
|
||||
error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}`
|
||||
--> $DIR/issue-88119.rs:19:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &T
|
||||
| ^^ cannot normalize `<&T as ConstName>::{constant#0}`
|
||||
|
|
||||
note: required for `&T` to implement `ConstName`
|
||||
--> $DIR/issue-88119.rs:19:35
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &T
|
||||
| ^^^^^^^^^ ^^
|
||||
LL | where
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
|
|
||||
note: required by a bound in `<&T as ConstName>`
|
||||
--> $DIR/issue-88119.rs:21:10
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
|
||||
| --------------------- unsatisfied trait bound introduced here
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
--> $DIR/issue-88119.rs:28:5
|
||||
error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
|
||||
--> $DIR/issue-88119.rs:26:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
|
||||
| ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
|
||||
|
|
||||
note: required for `&mut T` to implement `ConstName`
|
||||
--> $DIR/issue-88119.rs:26:35
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
|
||||
| ^^^^^^^^^ ^^^^^^
|
||||
LL | where
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
|
|
||||
note: required by a bound in `<&mut T as ConstName>`
|
||||
--> $DIR/issue-88119.rs:28:10
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
|
||||
| --------------------- unsatisfied trait bound introduced here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ fn bar<const N: usize>() {}
|
|||
fn foo<const N: usize>() {
|
||||
bar::<{ [1; N] }>();
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
bar::<{ [1; { N + 1 }] }>();
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -7,5 +7,14 @@ LL | bar::<{ [1; N] }>();
|
|||
= help: const parameters may only be used as standalone arguments, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/repeat_expr_hack_gives_right_generics.rs:22:19
|
||||
|
|
||||
LL | bar::<{ [1; { N + 1 }] }>();
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -10,11 +10,10 @@ fn foo<const W: usize, const H: usize>(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] {
|
|||
}
|
||||
|
||||
fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
//~^ ERROR the constant `W` is not of type `usize`
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR cannot transmute between types
|
||||
//~^ ERROR the constant `W` is not of type `usize`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
error: the constant `W` is not of type `usize`
|
||||
--> $DIR/transmute-fail.rs:12:42
|
||||
|
|
||||
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
| ^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:7:5
|
||||
|
|
||||
|
@ -7,17 +13,14 @@ LL | std::mem::transmute(v)
|
|||
= note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1])
|
||||
= note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:16:5
|
||||
error: the constant `W` is not of type `usize`
|
||||
--> $DIR/transmute-fail.rs:15:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:23:5
|
||||
--> $DIR/transmute-fail.rs:22:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -26,7 +29,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:30:5
|
||||
--> $DIR/transmute-fail.rs:29:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -35,7 +38,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:37:5
|
||||
--> $DIR/transmute-fail.rs:36:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -44,7 +47,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:50:5
|
||||
--> $DIR/transmute-fail.rs:49:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -53,7 +56,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[u32; W * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:57:5
|
||||
--> $DIR/transmute-fail.rs:56:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -62,7 +65,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:66:5
|
||||
--> $DIR/transmute-fail.rs:65:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -71,7 +74,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:75:5
|
||||
--> $DIR/transmute-fail.rs:74:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -80,7 +83,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:82:5
|
||||
--> $DIR/transmute-fail.rs:81:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -89,7 +92,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[u8; L * 2]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:89:5
|
||||
--> $DIR/transmute-fail.rs:88:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -98,7 +101,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[u16; L]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:96:5
|
||||
--> $DIR/transmute-fail.rs:95:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -107,7 +110,7 @@ LL | std::mem::transmute(v)
|
|||
= note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:105:5
|
||||
--> $DIR/transmute-fail.rs:104:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -115,19 +118,6 @@ LL | std::mem::transmute(v)
|
|||
= note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
|
||||
= note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transmute-fail.rs:12:53
|
||||
|
|
||||
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
| ^ expected `usize`, found `bool`
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transmute-fail.rs:12:67
|
||||
|
|
||||
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
| ^ expected `usize`, found `bool`
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0512.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0512`.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
fn foo<const N: usize>() -> [u8; N] {
|
||||
bar::<N>() //~ ERROR mismatched types
|
||||
bar::<N>()
|
||||
//~^ ERROR the constant `N` is not of type `u8`
|
||||
}
|
||||
|
||||
fn bar<const N: u8>() -> [u8; N] {}
|
||||
//~^ ERROR mismatched types
|
||||
//~^ ERROR the constant `N` is not of type `usize`
|
||||
//~| ERROR mismatched types
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
error: the constant `N` is not of type `usize`
|
||||
--> $DIR/type_mismatch.rs:6:26
|
||||
|
|
||||
LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| ^^^^^^^ expected `usize`, found `u8`
|
||||
|
||||
error: the constant `N` is not of type `u8`
|
||||
--> $DIR/type_mismatch.rs:2:11
|
||||
|
|
||||
|
@ -18,18 +24,6 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
|
|||
| |
|
||||
| implicitly returns `()` as its body has no tail or `return` expression
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:2:11
|
||||
|
|
||||
LL | bar::<N>()
|
||||
| ^ expected `u8`, found `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:6:31
|
||||
|
|
||||
LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| ^ expected `usize`, found `u8`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}`
|
||||
error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}`
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
|
|
||||
LL | B = A,
|
||||
| ^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`...
|
||||
note: ...which requires const-evaluating + checking `Foo::{constant#0}`...
|
||||
--> $DIR/issue-36163.rs:4:9
|
||||
|
|
||||
LL | B = A,
|
||||
|
@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`...
|
|||
|
|
||||
LL | const A: isize = Foo::B as isize;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
|
||||
= note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle
|
||||
note: cycle used when checking that `Foo` is well-formed
|
||||
--> $DIR/issue-36163.rs:3:1
|
||||
|
|
||||
|
|
|
@ -9,6 +9,5 @@ impl Fn(&isize) for Error {
|
|||
//~^ ERROR associated function in `impl` without body
|
||||
//~^^ ERROR method `foo` is not a member of trait `Fn` [E0407]
|
||||
//~^^^ ERROR associated type `B` not found for `Self` [E0220]
|
||||
//~| ERROR associated type `B` not found for `Self` [E0220]
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
@ -56,15 +56,7 @@ error[E0220]: associated type `B` not found for `Self`
|
|||
LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>;
|
||||
| ^ help: `Self` has the following associated type: `Output`
|
||||
|
||||
error[E0220]: associated type `B` not found for `Self`
|
||||
--> $DIR/issue-95023.rs:8:44
|
||||
|
|
||||
LL | fn foo<const N: usize>(&self) -> Self::B<{ N }>;
|
||||
| ^ help: `Self` has the following associated type: `Output`
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
|
|
|
@ -4,20 +4,11 @@ error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#0
|
|||
LL | fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] {
|
||||
| ^^^^^^^^^^^^^^^^ cannot normalize `process<T>::{constant#0}`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `the constant `T::make(P)` can be evaluated`
|
||||
--> $DIR/const-trait-bounds.rs:18:5
|
||||
error[E0284]: type annotations needed: cannot normalize `Struct<T, P>::field::{constant#0}`
|
||||
--> $DIR/const-trait-bounds.rs:20:12
|
||||
|
|
||||
LL | [u32; T::make(P)]:,
|
||||
| ^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `T::make(P)` can be evaluated`
|
||||
|
|
||||
note: required by a bound in `Struct`
|
||||
--> $DIR/const-trait-bounds.rs:18:11
|
||||
|
|
||||
LL | struct Struct<T: const Trait, const P: usize>
|
||||
| ------ required by a bound in this struct
|
||||
LL | where
|
||||
LL | [u32; T::make(P)]:,
|
||||
| ^^^^^^^^^^ required by this bound in `Struct`
|
||||
LL | field: [u32; T::make(P)],
|
||||
| ^^^^^^^^^^^^^^^^^ cannot normalize `Struct<T, P>::field::{constant#0}`
|
||||
|
||||
error[E0284]: type annotations needed: cannot normalize `process<T>::{constant#1}`
|
||||
--> $DIR/const-trait-bounds.rs:13:5
|
||||
|
|
|
@ -14,6 +14,5 @@ struct Wrapper<const C: <i32 as Trait>::Type> {}
|
|||
|
||||
impl<const C: usize> Wrapper<C> {}
|
||||
//~^ ERROR the constant `C` is not of type `<i32 as Trait>::Type`
|
||||
//~^^ ERROR mismatched types
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -20,17 +20,5 @@ note: required by a const generic parameter in `Wrapper`
|
|||
LL | struct Wrapper<const C: <i32 as Trait>::Type> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30
|
||||
|
|
||||
LL | impl<const C: usize> Wrapper<C> {}
|
||||
| ^ expected associated type, found `usize`
|
||||
|
|
||||
= note: expected associated type `<i32 as Trait>::Type`
|
||||
found type `usize`
|
||||
= help: consider constraining the associated type `<i32 as Trait>::Type` to `usize`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
struct S<const L: usize>;
|
||||
|
||||
impl<const N: i32> Copy for S<N> {}
|
||||
//~^ ERROR: mismatched types
|
||||
impl<const M: usize> Copy for S<M> {}
|
||||
//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
|
||||
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
|
||||
--> $DIR/bad-const-wf-doesnt-specialize.rs:10:1
|
||||
--> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
|
||||
|
|
||||
LL | impl<const N: i32> Copy for S<N> {}
|
||||
| -------------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl<const M: usize> Copy for S<M> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-const-wf-doesnt-specialize.rs:8:31
|
||||
|
|
||||
LL | impl<const N: i32> Copy for S<N> {}
|
||||
| ^ expected `usize`, found `i32`
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0119, E0308.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
|
|
|
@ -123,15 +123,15 @@ hir-stats Lifetime 24 ( 0.3%) 1 24
|
|||
hir-stats Mod 32 ( 0.4%) 1 32
|
||||
hir-stats ExprField 40 ( 0.4%) 1 40
|
||||
hir-stats TraitItemRef 56 ( 0.6%) 2 28
|
||||
hir-stats GenericArg 64 ( 0.7%) 4 16
|
||||
hir-stats - Type 16 ( 0.2%) 1
|
||||
hir-stats - Lifetime 48 ( 0.5%) 3
|
||||
hir-stats Local 64 ( 0.7%) 1 64
|
||||
hir-stats Param 64 ( 0.7%) 2 32
|
||||
hir-stats Body 72 ( 0.8%) 3 24
|
||||
hir-stats InlineAsm 72 ( 0.8%) 1 72
|
||||
hir-stats ImplItemRef 72 ( 0.8%) 2 36
|
||||
hir-stats Arm 80 ( 0.9%) 2 40
|
||||
hir-stats GenericArg 96 ( 1.1%) 4 24
|
||||
hir-stats - Type 24 ( 0.3%) 1
|
||||
hir-stats - Lifetime 72 ( 0.8%) 3
|
||||
hir-stats FieldDef 96 ( 1.1%) 2 48
|
||||
hir-stats Stmt 96 ( 1.1%) 3 32
|
||||
hir-stats - Let 32 ( 0.4%) 1
|
||||
|
@ -155,8 +155,8 @@ hir-stats Generics 560 ( 6.2%) 10 56
|
|||
hir-stats Ty 720 ( 8.0%) 15 48
|
||||
hir-stats - Ptr 48 ( 0.5%) 1
|
||||
hir-stats - Ref 48 ( 0.5%) 1
|
||||
hir-stats - Path 624 ( 6.9%) 13
|
||||
hir-stats Expr 768 ( 8.5%) 12 64
|
||||
hir-stats - Path 624 ( 7.0%) 13
|
||||
hir-stats Expr 768 ( 8.6%) 12 64
|
||||
hir-stats - Path 64 ( 0.7%) 1
|
||||
hir-stats - Struct 64 ( 0.7%) 1
|
||||
hir-stats - Match 64 ( 0.7%) 1
|
||||
|
@ -174,5 +174,5 @@ hir-stats - Use 352 ( 3.9%) 4
|
|||
hir-stats Path 1_240 (13.8%) 31 40
|
||||
hir-stats PathSegment 1_920 (21.4%) 40 48
|
||||
hir-stats ----------------------------------------------------------------
|
||||
hir-stats Total 8_992
|
||||
hir-stats Total 8_960
|
||||
hir-stats
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#![feature(non_lifetime_binders)]
|
||||
//~^ WARN the feature `non_lifetime_binders` is incomplete
|
||||
|
||||
fn b()
|
||||
where
|
||||
for<const C: usize> [(); C]: Copy,
|
||||
//~^ ERROR cannot capture late-bound const parameter in constant
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,19 +0,0 @@
|
|||
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/capture-late-ct-in-anon.rs:1:12
|
||||
|
|
||||
LL | #![feature(non_lifetime_binders)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: cannot capture late-bound const parameter in constant
|
||||
--> $DIR/capture-late-ct-in-anon.rs:6:30
|
||||
|
|
||||
LL | for<const C: usize> [(); C]: Copy,
|
||||
| -------------- ^
|
||||
| |
|
||||
| parameter defined here
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
|
@ -7,7 +7,6 @@ mod assert {
|
|||
where
|
||||
Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
|
||||
//~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
|
||||
//~| ERROR: mismatched types
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,13 +13,6 @@ LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>,
|
|||
note: required by a const generic parameter in `BikeshedIntrinsicFrom`
|
||||
--> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-101739-1.rs:8:41
|
||||
|
|
||||
LL | Dst: BikeshedIntrinsicFrom<Src, ASSUME_ALIGNMENT>,
|
||||
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0412.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0412`.
|
||||
|
|
|
@ -16,7 +16,7 @@ mod assert {
|
|||
where
|
||||
Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied
|
||||
Src,
|
||||
ASSUME_ALIGNMENT, //~ ERROR: mismatched types
|
||||
ASSUME_ALIGNMENT,
|
||||
ASSUME_LIFETIMES,
|
||||
ASSUME_VALIDITY,
|
||||
ASSUME_VISIBILITY,
|
||||
|
|
|
@ -9,13 +9,6 @@ LL | | ASSUME_VALIDITY,
|
|||
LL | | ASSUME_VISIBILITY,
|
||||
| |_____________________________- help: remove these generic arguments
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-101739-2.rs:19:13
|
||||
|
|
||||
LL | ASSUME_ALIGNMENT,
|
||||
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0308.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
For more information about this error, try `rustc --explain E0107`.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
|
||||
trait Trait {
|
||||
fn func<const N: u32>() -> [ (); N ]; //~ ERROR mismatched types
|
||||
fn func<const N: u32>() -> [ (); N ]; //~ ERROR the constant `N` is not of type `usize`
|
||||
}
|
||||
|
||||
struct S {}
|
||||
|
|
|
@ -4,11 +4,11 @@ error[E0308]: mismatched types
|
|||
LL | fn func<const N: u32>() -> [ (); { () }] {
|
||||
| ^^ expected `usize`, found `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/const-in-impl-fn-return-type.rs:8:38
|
||||
error: the constant `N` is not of type `usize`
|
||||
--> $DIR/const-in-impl-fn-return-type.rs:8:32
|
||||
|
|
||||
LL | fn func<const N: u32>() -> [ (); N ];
|
||||
| ^ expected `usize`, found `u32`
|
||||
| ^^^^^^^^^ expected `usize`, found `u32`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue