mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 19:17:43 +00:00
Auto merge of #58503 - varkor:const-generics-hir, r=petrochenkov
Add const generics to the HIR Split out from https://github.com/rust-lang/rust/pull/53645. cc @yodaldevoid r? @eddyb
This commit is contained in:
commit
32471f7ea4
@ -52,13 +52,13 @@ pub enum Def {
|
|||||||
AssociatedExistential(DefId),
|
AssociatedExistential(DefId),
|
||||||
PrimTy(hir::PrimTy),
|
PrimTy(hir::PrimTy),
|
||||||
TyParam(DefId),
|
TyParam(DefId),
|
||||||
ConstParam(DefId),
|
|
||||||
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
|
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
|
||||||
ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
|
ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
|
||||||
|
|
||||||
// Value namespace
|
// Value namespace
|
||||||
Fn(DefId),
|
Fn(DefId),
|
||||||
Const(DefId),
|
Const(DefId),
|
||||||
|
ConstParam(DefId),
|
||||||
Static(DefId, bool /* is_mutbl */),
|
Static(DefId, bool /* is_mutbl */),
|
||||||
StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor
|
StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor
|
||||||
VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant
|
VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant
|
||||||
|
@ -334,6 +334,7 @@ pub trait Visitor<'v> : Sized {
|
|||||||
match generic_arg {
|
match generic_arg {
|
||||||
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||||
|
GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
||||||
@ -752,6 +753,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
|
|||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {}
|
GenericParamKind::Lifetime { .. } => {}
|
||||||
GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
|
GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
|
||||||
|
GenericParamKind::Const { ref ty } => visitor.visit_ty(ty),
|
||||||
}
|
}
|
||||||
walk_list!(visitor, visit_param_bound, ¶m.bounds);
|
walk_list!(visitor, visit_param_bound, ¶m.bounds);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ use crate::hir::HirVec;
|
|||||||
use crate::hir::map::{DefKey, DefPathData, Definitions};
|
use crate::hir::map::{DefKey, DefPathData, Definitions};
|
||||||
use crate::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
|
use crate::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
|
||||||
use crate::hir::def::{Def, PathResolution, PerNS};
|
use crate::hir::def::{Def, PathResolution, PerNS};
|
||||||
use crate::hir::GenericArg;
|
use crate::hir::{GenericArg, ConstArg};
|
||||||
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
|
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
|
||||||
ELIDED_LIFETIMES_IN_PATHS};
|
ELIDED_LIFETIMES_IN_PATHS};
|
||||||
use crate::middle::cstore::CrateStore;
|
use crate::middle::cstore::CrateStore;
|
||||||
@ -1172,13 +1172,10 @@ impl<'a> LoweringContext<'a> {
|
|||||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
||||||
ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
|
ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
|
||||||
ast::GenericArg::Const(ct) => {
|
ast::GenericArg::Const(ct) => {
|
||||||
// FIXME(const_generics): const generics are not yet defined in the HIR.
|
GenericArg::Const(ConstArg {
|
||||||
self.sess.struct_span_err(
|
value: self.lower_anon_const(&ct),
|
||||||
ct.value.span,
|
span: ct.value.span,
|
||||||
"const generics in any position are currently unsupported",
|
})
|
||||||
).emit();
|
|
||||||
self.sess.abort_if_errors();
|
|
||||||
bug!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2520,14 +2517,10 @@ impl<'a> LoweringContext<'a> {
|
|||||||
|
|
||||||
(hir::ParamName::Plain(ident), kind)
|
(hir::ParamName::Plain(ident), kind)
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { .. } => {
|
GenericParamKind::Const { ref ty } => {
|
||||||
// FIXME(const_generics): const generics are not yet defined in the HIR.
|
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const {
|
||||||
self.sess.struct_span_err(
|
ty: self.lower_ty(&ty, ImplTraitContext::disallowed()),
|
||||||
param.ident.span,
|
})
|
||||||
"const generics in any position are currently unsupported",
|
|
||||||
).emit();
|
|
||||||
self.sess.abort_if_errors();
|
|
||||||
bug!();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -398,6 +398,7 @@ impl<'hir> Map<'hir> {
|
|||||||
Some(match param.kind {
|
Some(match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => Def::Local(param.id),
|
GenericParamKind::Lifetime { .. } => Def::Local(param.id),
|
||||||
GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)),
|
GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)),
|
||||||
|
GenericParamKind::Const { .. } => Def::ConstParam(self.local_def_id(param.id)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,10 +389,17 @@ impl PathSegment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
|
pub struct ConstArg {
|
||||||
|
pub value: AnonConst,
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum GenericArg {
|
pub enum GenericArg {
|
||||||
Lifetime(Lifetime),
|
Lifetime(Lifetime),
|
||||||
Type(Ty),
|
Type(Ty),
|
||||||
|
Const(ConstArg),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericArg {
|
impl GenericArg {
|
||||||
@ -400,6 +407,7 @@ impl GenericArg {
|
|||||||
match self {
|
match self {
|
||||||
GenericArg::Lifetime(l) => l.span,
|
GenericArg::Lifetime(l) => l.span,
|
||||||
GenericArg::Type(t) => t.span,
|
GenericArg::Type(t) => t.span,
|
||||||
|
GenericArg::Const(c) => c.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,6 +415,7 @@ impl GenericArg {
|
|||||||
match self {
|
match self {
|
||||||
GenericArg::Lifetime(l) => l.id,
|
GenericArg::Lifetime(l) => l.id,
|
||||||
GenericArg::Type(t) => t.id,
|
GenericArg::Type(t) => t.id,
|
||||||
|
GenericArg::Const(c) => c.value.id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,6 +457,7 @@ impl GenericArgs {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
GenericArg::Const(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -464,6 +474,7 @@ impl GenericArgs {
|
|||||||
match arg {
|
match arg {
|
||||||
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
|
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
|
||||||
GenericArg::Type(_) => own_counts.types += 1,
|
GenericArg::Type(_) => own_counts.types += 1,
|
||||||
|
GenericArg::Const(_) => own_counts.consts += 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,6 +539,9 @@ pub enum GenericParamKind {
|
|||||||
Type {
|
Type {
|
||||||
default: Option<P<Ty>>,
|
default: Option<P<Ty>>,
|
||||||
synthetic: Option<SyntheticTyParamKind>,
|
synthetic: Option<SyntheticTyParamKind>,
|
||||||
|
},
|
||||||
|
Const {
|
||||||
|
ty: P<Ty>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,6 +562,7 @@ pub struct GenericParam {
|
|||||||
pub struct GenericParamCount {
|
pub struct GenericParamCount {
|
||||||
pub lifetimes: usize,
|
pub lifetimes: usize,
|
||||||
pub types: usize,
|
pub types: usize,
|
||||||
|
pub consts: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents lifetimes and type parameters attached to a declaration
|
/// Represents lifetimes and type parameters attached to a declaration
|
||||||
@ -582,6 +597,7 @@ impl Generics {
|
|||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
|
GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
|
||||||
GenericParamKind::Type { .. } => own_counts.types += 1,
|
GenericParamKind::Type { .. } => own_counts.types += 1,
|
||||||
|
GenericParamKind::Const { .. } => own_counts.consts += 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1302,7 +1318,7 @@ impl BodyOwnerKind {
|
|||||||
/// These are usually found nested inside types (e.g., array lengths)
|
/// These are usually found nested inside types (e.g., array lengths)
|
||||||
/// or expressions (e.g., repeat counts), and also used to define
|
/// or expressions (e.g., repeat counts), and also used to define
|
||||||
/// explicit discriminant values for enum variants.
|
/// explicit discriminant values for enum variants.
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct AnonConst {
|
pub struct AnonConst {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
|
@ -64,19 +64,6 @@ impl hir::Pat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const(&self) -> bool {
|
|
||||||
match self.node {
|
|
||||||
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
|
|
||||||
PatKind::Path(hir::QPath::Resolved(_, ref path)) => {
|
|
||||||
match path.def {
|
|
||||||
Def::Const(..) | Def::AssociatedConst(..) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
|
||||||
/// `match foo() { Some(a) => (), None => () }`
|
/// `match foo() { Some(a) => (), None => () }`
|
||||||
pub fn each_binding<F>(&self, mut f: F)
|
pub fn each_binding<F>(&self, mut f: F)
|
||||||
|
@ -1711,31 +1711,25 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut types = vec![];
|
let mut nonelided_generic_args: bool = false;
|
||||||
let mut elide_lifetimes = true;
|
let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
|
||||||
for arg in &generic_args.args {
|
GenericArg::Lifetime(lt) => lt.is_elided(),
|
||||||
match arg {
|
_ => {
|
||||||
GenericArg::Lifetime(lt) => {
|
nonelided_generic_args = true;
|
||||||
if !lt.is_elided() {
|
true
|
||||||
elide_lifetimes = false;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
GenericArg::Type(ty) => {
|
|
||||||
types.push(ty);
|
if nonelided_generic_args {
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !elide_lifetimes {
|
|
||||||
start_or_comma(self)?;
|
start_or_comma(self)?;
|
||||||
self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| {
|
self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| {
|
||||||
match generic_arg {
|
match generic_arg {
|
||||||
GenericArg::Lifetime(lt) => s.print_lifetime(lt),
|
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
|
||||||
|
GenericArg::Lifetime(_) => Ok(()),
|
||||||
GenericArg::Type(ty) => s.print_type(ty),
|
GenericArg::Type(ty) => s.print_type(ty),
|
||||||
|
GenericArg::Const(ct) => s.print_anon_const(&ct.value),
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
} else if !types.is_empty() {
|
|
||||||
start_or_comma(self)?;
|
|
||||||
self.commasep(Inconsistent, &types, |s, ty| s.print_type(&ty))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eddyb) This would leak into error messages, e.g.:
|
// FIXME(eddyb) This would leak into error messages, e.g.:
|
||||||
@ -2106,7 +2100,12 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
|
pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
|
||||||
|
if let GenericParamKind::Const { .. } = param.kind {
|
||||||
|
self.word_space("const")?;
|
||||||
|
}
|
||||||
|
|
||||||
self.print_ident(param.name.ident())?;
|
self.print_ident(param.name.ident())?;
|
||||||
|
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
let mut sep = ":";
|
let mut sep = ":";
|
||||||
@ -2133,6 +2132,10 @@ impl<'a> State<'a> {
|
|||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Const { ref ty } => {
|
||||||
|
self.word_space(":")?;
|
||||||
|
self.print_type(ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,9 +179,15 @@ impl_stable_hash_for!(struct hir::PathSegment {
|
|||||||
args
|
args
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct hir::ConstArg {
|
||||||
|
value,
|
||||||
|
span,
|
||||||
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(enum hir::GenericArg {
|
impl_stable_hash_for!(enum hir::GenericArg {
|
||||||
Lifetime(lt),
|
Lifetime(lt),
|
||||||
Type(ty)
|
Type(ty),
|
||||||
|
Const(ct),
|
||||||
});
|
});
|
||||||
|
|
||||||
impl_stable_hash_for!(struct hir::GenericArgs {
|
impl_stable_hash_for!(struct hir::GenericArgs {
|
||||||
@ -231,6 +237,9 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {
|
|||||||
default.hash_stable(hcx, hasher);
|
default.hash_stable(hcx, hasher);
|
||||||
synthetic.hash_stable(hcx, hasher);
|
synthetic.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
|
hir::GenericParamKind::Const { ref ty } => {
|
||||||
|
ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,7 +704,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||||||
hir_id, expr_ty, def);
|
hir_id, expr_ty, def);
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
|
Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::ConstParam(..) |
|
||||||
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
|
Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
|
||||||
Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
|
Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
|
||||||
}
|
}
|
||||||
|
@ -315,8 +315,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||||||
Node::Ty(_) |
|
Node::Ty(_) |
|
||||||
Node::MacroDef(_) => {}
|
Node::MacroDef(_) => {}
|
||||||
_ => {
|
_ => {
|
||||||
bug!("found unexpected thingy in worklist: {}",
|
bug!(
|
||||||
self.tcx.hir().node_to_string(search_item))
|
"found unexpected node kind in worklist: {} ({:?})",
|
||||||
|
self.tcx.hir().node_to_string(search_item),
|
||||||
|
node,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,23 +527,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let mut type_count = 0;
|
let mut non_lifetime_count = 0;
|
||||||
let lifetimes = generics
|
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } |
|
||||||
type_count += 1;
|
GenericParamKind::Const { .. } => {
|
||||||
|
non_lifetime_count += 1;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
}).collect();
|
||||||
.collect();
|
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index: index + type_count,
|
next_early_index: index + non_lifetime_count,
|
||||||
abstract_type_parent: true,
|
abstract_type_parent: true,
|
||||||
track_lifetime_uses,
|
track_lifetime_uses,
|
||||||
s: ROOT_SCOPE,
|
s: ROOT_SCOPE,
|
||||||
@ -708,7 +705,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
let mut elision = None;
|
let mut elision = None;
|
||||||
let mut lifetimes = FxHashMap::default();
|
let mut lifetimes = FxHashMap::default();
|
||||||
let mut type_count = 0;
|
let mut non_lifetime_count = 0;
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
@ -725,12 +722,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
lifetimes.insert(name, reg);
|
lifetimes.insert(name, reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } |
|
||||||
type_count += 1;
|
GenericParamKind::Const { .. } => {
|
||||||
|
non_lifetime_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let next_early_index = index + type_count;
|
let next_early_index = index + non_lifetime_count;
|
||||||
|
|
||||||
if let Some(elision_region) = elision {
|
if let Some(elision_region) = elision {
|
||||||
let scope = Scope::Elision {
|
let scope = Scope::Elision {
|
||||||
@ -788,23 +786,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
let generics = &trait_item.generics;
|
let generics = &trait_item.generics;
|
||||||
let mut index = self.next_early_index();
|
let mut index = self.next_early_index();
|
||||||
debug!("visit_ty: index = {}", index);
|
debug!("visit_ty: index = {}", index);
|
||||||
let mut type_count = 0;
|
let mut non_lifetime_count = 0;
|
||||||
let lifetimes = generics
|
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } |
|
||||||
type_count += 1;
|
GenericParamKind::Const { .. } => {
|
||||||
|
non_lifetime_count += 1;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
}).collect();
|
||||||
.collect();
|
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index: index + type_count,
|
next_early_index: index + non_lifetime_count,
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
abstract_type_parent: true,
|
abstract_type_parent: true,
|
||||||
@ -842,24 +837,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
Type(ref ty) => {
|
Type(ref ty) => {
|
||||||
let generics = &impl_item.generics;
|
let generics = &impl_item.generics;
|
||||||
let mut index = self.next_early_index();
|
let mut index = self.next_early_index();
|
||||||
let mut next_early_index = index;
|
let mut non_lifetime_count = 0;
|
||||||
debug!("visit_ty: index = {}", index);
|
debug!("visit_ty: index = {}", index);
|
||||||
let lifetimes = generics
|
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Const { .. } |
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } => {
|
||||||
next_early_index += 1;
|
non_lifetime_count += 1;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
}).collect();
|
||||||
.collect();
|
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
lifetimes,
|
lifetimes,
|
||||||
next_early_index,
|
next_early_index: index + non_lifetime_count,
|
||||||
s: self.scope,
|
s: self.scope,
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
abstract_type_parent: true,
|
abstract_type_parent: true,
|
||||||
@ -874,10 +866,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
let mut index = self.next_early_index();
|
let mut index = self.next_early_index();
|
||||||
let mut next_early_index = index;
|
let mut next_early_index = index;
|
||||||
debug!("visit_ty: index = {}", index);
|
debug!("visit_ty: index = {}", index);
|
||||||
let lifetimes = generics
|
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
||||||
}
|
}
|
||||||
@ -885,8 +874,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
next_early_index += 1;
|
next_early_index += 1;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
GenericParamKind::Const { .. } => {
|
||||||
.collect();
|
next_early_index += 1;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
lifetimes,
|
lifetimes,
|
||||||
@ -950,6 +942,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
self.visit_ty(&ty);
|
self.visit_ty(&ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Const { ref ty, .. } => {
|
||||||
|
walk_list!(self, visit_param_bound, ¶m.bounds);
|
||||||
|
self.visit_ty(&ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for predicate in &generics.where_clause.predicates {
|
for predicate in &generics.where_clause.predicates {
|
||||||
@ -1395,6 +1391,10 @@ fn object_lifetime_defaults_for_item(
|
|||||||
Set1::Many => Set1::Many,
|
Set1::Many => Set1::Many,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Const { .. } => {
|
||||||
|
// Generic consts don't impose any constraints.
|
||||||
|
None
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@ -1703,11 +1703,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut type_count = 0;
|
let mut non_lifetime_count = 0;
|
||||||
let lifetimes = generics
|
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
GenericParamKind::Lifetime { .. } => {
|
GenericParamKind::Lifetime { .. } => {
|
||||||
if self.map.late_bound.contains(¶m.id) {
|
if self.map.late_bound.contains(¶m.id) {
|
||||||
Some(Region::late(&self.tcx.hir(), param))
|
Some(Region::late(&self.tcx.hir(), param))
|
||||||
@ -1715,13 +1712,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||||||
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
Some(Region::early(&self.tcx.hir(), &mut index, param))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } |
|
||||||
type_count += 1;
|
GenericParamKind::Const { .. } => {
|
||||||
|
non_lifetime_count += 1;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
}).collect();
|
||||||
.collect();
|
let next_early_index = index + non_lifetime_count;
|
||||||
let next_early_index = index + type_count;
|
|
||||||
|
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
lifetimes,
|
lifetimes,
|
||||||
@ -2011,6 +2008,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
GenericArg::Const(ct) => {
|
||||||
|
self.visit_anon_const(&ct.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2768,8 +2768,9 @@ fn insert_late_bound_lifetimes(
|
|||||||
match param.kind {
|
match param.kind {
|
||||||
hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
|
hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
|
||||||
|
|
||||||
// Types are not late-bound.
|
// Neither types nor consts are late-bound.
|
||||||
hir::GenericParamKind::Type { .. } => continue,
|
hir::GenericParamKind::Type { .. }
|
||||||
|
| hir::GenericParamKind::Const { .. } => continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
let lt_name = hir::LifetimeName::Param(param.name.modern());
|
let lt_name = hir::LifetimeName::Param(param.name.modern());
|
||||||
|
@ -907,11 +907,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
|||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {}
|
GenericParamKind::Lifetime { .. } => {}
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } |
|
||||||
let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
|
GenericParamKind::Const { .. } => {
|
||||||
|
let mut err = cx.struct_span_lint(
|
||||||
|
NO_MANGLE_GENERIC_ITEMS,
|
||||||
it.span,
|
it.span,
|
||||||
"functions generic over \
|
"functions generic over types or consts must be mangled",
|
||||||
types must be mangled");
|
);
|
||||||
err.span_suggestion_short(
|
err.span_suggestion_short(
|
||||||
no_mangle_attr.span,
|
no_mangle_attr.span,
|
||||||
"remove this attribute",
|
"remove this attribute",
|
||||||
@ -1791,14 +1793,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
|
|||||||
|
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
let param_name = match param.kind {
|
let param_name = match param.kind {
|
||||||
hir::GenericParamKind::Lifetime { .. } => { continue; },
|
hir::GenericParamKind::Lifetime { .. } => continue,
|
||||||
hir::GenericParamKind::Type { .. } => {
|
hir::GenericParamKind::Type { .. } => {
|
||||||
match param.name {
|
match param.name {
|
||||||
hir::ParamName::Fresh(_) => { continue; },
|
hir::ParamName::Fresh(_) => continue,
|
||||||
hir::ParamName::Error => { continue; },
|
hir::ParamName::Error => continue,
|
||||||
hir::ParamName::Plain(name) => name.to_string()
|
hir::ParamName::Plain(name) => name.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hir::GenericParamKind::Const { .. } => continue,
|
||||||
};
|
};
|
||||||
let bound_spans = self.collect_outlives_bound_spans(
|
let bound_spans = self.collect_outlives_bound_spans(
|
||||||
cx, def_id, ¶m_name, ¶m.bounds, infer_static
|
cx, def_id, ¶m_name, ¶m.bounds, infer_static
|
||||||
|
@ -455,6 +455,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_generic_param(&mut self, cx: &LateContext<'_, '_>, param: &hir::GenericParam) {
|
||||||
|
if let GenericParamKind::Const { .. } = param.kind {
|
||||||
|
NonUpperCaseGlobals::check_upper_case(
|
||||||
|
cx,
|
||||||
|
"const parameter",
|
||||||
|
¶m.name.ident(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1331,6 +1331,29 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_info_for_const_param(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||||
|
debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id);
|
||||||
|
let tcx = self.tcx;
|
||||||
|
Entry {
|
||||||
|
kind: EntryKind::Type,
|
||||||
|
visibility: self.lazy(&ty::Visibility::Public),
|
||||||
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
|
attributes: LazySeq::empty(),
|
||||||
|
children: LazySeq::empty(),
|
||||||
|
stability: None,
|
||||||
|
deprecation: None,
|
||||||
|
|
||||||
|
ty: Some(self.encode_item_type(def_id)),
|
||||||
|
inherent_impls: LazySeq::empty(),
|
||||||
|
variances: LazySeq::empty(),
|
||||||
|
generics: None,
|
||||||
|
predicates: None,
|
||||||
|
predicates_defined_on: None,
|
||||||
|
|
||||||
|
mir: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
|
fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||||
debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
|
debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
@ -1684,6 +1707,11 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
|||||||
let encode_info = IsolatedEncoder::encode_info_for_ty_param;
|
let encode_info = IsolatedEncoder::encode_info_for_ty_param;
|
||||||
self.record(def_id, encode_info, (def_id, has_default));
|
self.record(def_id, encode_info, (def_id, has_default));
|
||||||
}
|
}
|
||||||
|
hir::GenericParamKind::Const { .. } => {
|
||||||
|
let def_id = self.tcx.hir().local_def_id(param.id);
|
||||||
|
let encode_info = IsolatedEncoder::encode_info_for_const_param;
|
||||||
|
self.record(def_id, encode_info, def_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1090,7 +1090,10 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
hir::GenericParamKind::Lifetime { .. } => {}
|
hir::GenericParamKind::Lifetime { .. } => {}
|
||||||
hir::GenericParamKind::Type { .. } => return,
|
hir::GenericParamKind::Type { .. } |
|
||||||
|
hir::GenericParamKind::Const { .. } => {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,19 +500,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||||||
args.next();
|
args.next();
|
||||||
params.next();
|
params.next();
|
||||||
}
|
}
|
||||||
(GenericArg::Lifetime(_), GenericParamDefKind::Type { .. }) => {
|
(GenericArg::Type(_), GenericParamDefKind::Lifetime)
|
||||||
// We expected a type argument, but got a lifetime
|
| (GenericArg::Const(_), GenericParamDefKind::Lifetime) => {
|
||||||
// argument. This is an error, but we need to handle it
|
// We expected a lifetime argument, but got a type or const
|
||||||
// gracefully so we can report sensible errors. In this
|
|
||||||
// case, we're simply going to infer this argument.
|
|
||||||
args.next();
|
|
||||||
}
|
|
||||||
(GenericArg::Type(_), GenericParamDefKind::Lifetime) => {
|
|
||||||
// We expected a lifetime argument, but got a type
|
|
||||||
// argument. That means we're inferring the lifetimes.
|
// argument. That means we're inferring the lifetimes.
|
||||||
substs.push(inferred_kind(None, param, infer_types));
|
substs.push(inferred_kind(None, param, infer_types));
|
||||||
params.next();
|
params.next();
|
||||||
}
|
}
|
||||||
|
(_, _) => {
|
||||||
|
// We expected one kind of parameter, but the user provided
|
||||||
|
// another. This is an error, but we need to handle it
|
||||||
|
// gracefully so we can report sensible errors.
|
||||||
|
// In this case, we're simply going to infer this argument.
|
||||||
|
args.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Some(_), None) => {
|
(Some(_), None) => {
|
||||||
@ -524,12 +525,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||||||
(None, Some(¶m)) => {
|
(None, Some(¶m)) => {
|
||||||
// If there are fewer arguments than parameters, it means
|
// If there are fewer arguments than parameters, it means
|
||||||
// we're inferring the remaining arguments.
|
// we're inferring the remaining arguments.
|
||||||
match param.kind {
|
substs.push(inferred_kind(Some(&substs), param, infer_types));
|
||||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Type { .. } => {
|
|
||||||
let kind = inferred_kind(Some(&substs), param, infer_types);
|
|
||||||
substs.push(kind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args.next();
|
args.next();
|
||||||
params.next();
|
params.next();
|
||||||
}
|
}
|
||||||
@ -1459,9 +1455,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||||||
let mut has_err = false;
|
let mut has_err = false;
|
||||||
for segment in segments {
|
for segment in segments {
|
||||||
segment.with_generic_args(|generic_args| {
|
segment.with_generic_args(|generic_args| {
|
||||||
let (mut err_for_lt, mut err_for_ty) = (false, false);
|
let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
|
||||||
for arg in &generic_args.args {
|
for arg in &generic_args.args {
|
||||||
let (mut span_err, span, kind) = match arg {
|
let (mut span_err, span, kind) = match arg {
|
||||||
|
// FIXME(varkor): unify E0109, E0110 and E0111.
|
||||||
hir::GenericArg::Lifetime(lt) => {
|
hir::GenericArg::Lifetime(lt) => {
|
||||||
if err_for_lt { continue }
|
if err_for_lt { continue }
|
||||||
err_for_lt = true;
|
err_for_lt = true;
|
||||||
@ -1480,10 +1477,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
|||||||
ty.span,
|
ty.span,
|
||||||
"type")
|
"type")
|
||||||
}
|
}
|
||||||
|
hir::GenericArg::Const(ct) => {
|
||||||
|
if err_for_ct { continue }
|
||||||
|
err_for_ct = true;
|
||||||
|
(struct_span_err!(self.tcx().sess, ct.span, E0111,
|
||||||
|
"const parameters are not allowed on this type"),
|
||||||
|
ct.span,
|
||||||
|
"const")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
span_err.span_label(span, format!("{} argument not allowed", kind))
|
span_err.span_label(span, format!("{} argument not allowed", kind))
|
||||||
.emit();
|
.emit();
|
||||||
if err_for_lt && err_for_ty {
|
if err_for_lt && err_for_ty && err_for_ct {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -840,7 +840,8 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
let bounds = impl_m.generics.params.iter().find_map(|param| {
|
let bounds = impl_m.generics.params.iter().find_map(|param| {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => None,
|
GenericParamKind::Lifetime { .. } => None,
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } |
|
||||||
|
GenericParamKind::Const { .. } => {
|
||||||
if param.hir_id == impl_hir_id {
|
if param.hir_id == impl_hir_id {
|
||||||
Some(¶m.bounds)
|
Some(¶m.bounds)
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,6 +132,10 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
|
|||||||
self.tcx.type_of(def_id);
|
self.tcx.type_of(def_id);
|
||||||
}
|
}
|
||||||
hir::GenericParamKind::Type { .. } => {}
|
hir::GenericParamKind::Type { .. } => {}
|
||||||
|
hir::GenericParamKind::Const { .. } => {
|
||||||
|
let def_id = self.tcx.hir().local_def_id(param.id);
|
||||||
|
self.tcx.type_of(def_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
intravisit::walk_generics(self, generics);
|
intravisit::walk_generics(self, generics);
|
||||||
@ -1041,6 +1045,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
|
|||||||
i += 1;
|
i += 1;
|
||||||
Some(ty_param)
|
Some(ty_param)
|
||||||
}
|
}
|
||||||
|
GenericParamKind::Const { .. } => {
|
||||||
|
if param.name.ident().name == keywords::SelfUpper.name() {
|
||||||
|
span_bug!(
|
||||||
|
param.span,
|
||||||
|
"`Self` should not be the name of a regular parameter",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit an error, but skip the parameter rather than aborting to
|
||||||
|
// continue to get other errors.
|
||||||
|
tcx.sess.struct_span_err(
|
||||||
|
param.span,
|
||||||
|
"const generics in any position are currently unsupported",
|
||||||
|
).emit();
|
||||||
|
None
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -1301,10 +1321,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Node::GenericParam(param) => match ¶m.kind {
|
Node::GenericParam(param) => match ¶m.kind {
|
||||||
hir::GenericParamKind::Type {
|
hir::GenericParamKind::Type { default: Some(ref ty), .. } |
|
||||||
default: Some(ref ty),
|
hir::GenericParamKind::Const { ref ty, .. } => {
|
||||||
..
|
icx.to_ty(ty)
|
||||||
} => icx.to_ty(ty),
|
}
|
||||||
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
|
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1326,6 +1326,10 @@ type X = u32; // ok!
|
|||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0111: r##"
|
||||||
|
You tried to give a const parameter to a type which doesn't need it.
|
||||||
|
"##,
|
||||||
|
|
||||||
E0116: r##"
|
E0116: r##"
|
||||||
You can only define an inherent implementation for a type in the same crate
|
You can only define an inherent implementation for a type in the same crate
|
||||||
where the type was defined. For example, an `impl` block as below is not allowed
|
where the type was defined. For example, an `impl` block as below is not allowed
|
||||||
|
@ -773,6 +773,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Lifetime => {}
|
GenericParamDefKind::Lifetime => {}
|
||||||
|
GenericParamDefKind::Const { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,6 +1258,15 @@ impl Clean<Lifetime> for hir::GenericParam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clean<Constant> for hir::ConstArg {
|
||||||
|
fn clean(&self, cx: &DocContext) -> Constant {
|
||||||
|
Constant {
|
||||||
|
type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx),
|
||||||
|
expr: print_const_expr(cx, self.value.body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
|
impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
|
||||||
fn clean(&self, _cx: &DocContext) -> Lifetime {
|
fn clean(&self, _cx: &DocContext) -> Lifetime {
|
||||||
Lifetime(self.name.to_string())
|
Lifetime(self.name.to_string())
|
||||||
@ -1423,6 +1432,10 @@ pub enum GenericParamDefKind {
|
|||||||
default: Option<Type>,
|
default: Option<Type>,
|
||||||
synthetic: Option<hir::SyntheticTyParamKind>,
|
synthetic: Option<hir::SyntheticTyParamKind>,
|
||||||
},
|
},
|
||||||
|
Const {
|
||||||
|
did: DefId,
|
||||||
|
ty: Type,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||||
@ -1435,7 +1448,10 @@ pub struct GenericParamDef {
|
|||||||
impl GenericParamDef {
|
impl GenericParamDef {
|
||||||
pub fn is_synthetic_type_param(&self) -> bool {
|
pub fn is_synthetic_type_param(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
GenericParamDefKind::Lifetime => false,
|
GenericParamDefKind::Lifetime |
|
||||||
|
GenericParamDefKind::Const { .. } => {
|
||||||
|
false
|
||||||
|
}
|
||||||
GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
|
GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1491,7 +1507,7 @@ impl Clean<GenericParamDef> for hir::GenericParam {
|
|||||||
};
|
};
|
||||||
(name, GenericParamDefKind::Lifetime)
|
(name, GenericParamDefKind::Lifetime)
|
||||||
}
|
}
|
||||||
hir::GenericParamKind::Type { ref default, synthetic, .. } => {
|
hir::GenericParamKind::Type { ref default, synthetic } => {
|
||||||
(self.name.ident().name.clean(cx), GenericParamDefKind::Type {
|
(self.name.ident().name.clean(cx), GenericParamDefKind::Type {
|
||||||
did: cx.tcx.hir().local_def_id(self.id),
|
did: cx.tcx.hir().local_def_id(self.id),
|
||||||
bounds: self.bounds.clean(cx),
|
bounds: self.bounds.clean(cx),
|
||||||
@ -1499,6 +1515,12 @@ impl Clean<GenericParamDef> for hir::GenericParam {
|
|||||||
synthetic: synthetic,
|
synthetic: synthetic,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
hir::GenericParamKind::Const { ref ty } => {
|
||||||
|
(self.name.ident().name.clean(cx), GenericParamDefKind::Const {
|
||||||
|
did: cx.tcx.hir().local_def_id(self.id),
|
||||||
|
ty: ty.clean(cx),
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GenericParamDef {
|
GenericParamDef {
|
||||||
@ -1538,6 +1560,7 @@ impl Clean<Generics> for hir::Generics {
|
|||||||
GenericParamDefKind::Type { did, ref bounds, .. } => {
|
GenericParamDefKind::Type { did, ref bounds, .. } => {
|
||||||
cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
|
cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
|
||||||
}
|
}
|
||||||
|
GenericParamDefKind::Const { .. } => unreachable!(),
|
||||||
}
|
}
|
||||||
param
|
param
|
||||||
})
|
})
|
||||||
@ -1571,6 +1594,7 @@ impl Clean<Generics> for hir::Generics {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GenericParamDefKind::Const { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2549,6 +2573,7 @@ impl Clean<Type> for hir::Ty {
|
|||||||
let provided_params = &path.segments.last().expect("segments were empty");
|
let provided_params = &path.segments.last().expect("segments were empty");
|
||||||
let mut ty_substs = FxHashMap::default();
|
let mut ty_substs = FxHashMap::default();
|
||||||
let mut lt_substs = FxHashMap::default();
|
let mut lt_substs = FxHashMap::default();
|
||||||
|
let mut const_substs = FxHashMap::default();
|
||||||
provided_params.with_generic_args(|generic_args| {
|
provided_params.with_generic_args(|generic_args| {
|
||||||
let mut indices: GenericParamCount = Default::default();
|
let mut indices: GenericParamCount = Default::default();
|
||||||
for param in generics.params.iter() {
|
for param in generics.params.iter() {
|
||||||
@ -2557,7 +2582,7 @@ impl Clean<Type> for hir::Ty {
|
|||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
let lifetime = generic_args.args.iter().find_map(|arg| {
|
let lifetime = generic_args.args.iter().find_map(|arg| {
|
||||||
match arg {
|
match arg {
|
||||||
GenericArg::Lifetime(lt) => {
|
hir::GenericArg::Lifetime(lt) => {
|
||||||
if indices.lifetimes == j {
|
if indices.lifetimes == j {
|
||||||
return Some(lt);
|
return Some(lt);
|
||||||
}
|
}
|
||||||
@ -2582,7 +2607,7 @@ impl Clean<Type> for hir::Ty {
|
|||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
let type_ = generic_args.args.iter().find_map(|arg| {
|
let type_ = generic_args.args.iter().find_map(|arg| {
|
||||||
match arg {
|
match arg {
|
||||||
GenericArg::Type(ty) => {
|
hir::GenericArg::Type(ty) => {
|
||||||
if indices.types == j {
|
if indices.types == j {
|
||||||
return Some(ty);
|
return Some(ty);
|
||||||
}
|
}
|
||||||
@ -2600,10 +2625,32 @@ impl Clean<Type> for hir::Ty {
|
|||||||
}
|
}
|
||||||
indices.types += 1;
|
indices.types += 1;
|
||||||
}
|
}
|
||||||
|
hir::GenericParamKind::Const { .. } => {
|
||||||
|
let const_param_def =
|
||||||
|
Def::ConstParam(cx.tcx.hir().local_def_id(param.id));
|
||||||
|
let mut j = 0;
|
||||||
|
let const_ = generic_args.args.iter().find_map(|arg| {
|
||||||
|
match arg {
|
||||||
|
hir::GenericArg::Const(ct) => {
|
||||||
|
if indices.consts == j {
|
||||||
|
return Some(ct);
|
||||||
|
}
|
||||||
|
j += 1;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(ct) = const_.cloned() {
|
||||||
|
const_substs.insert(const_param_def, ct.clean(cx));
|
||||||
|
}
|
||||||
|
// FIXME(const_generics:defaults)
|
||||||
|
indices.consts += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
|
return cx.enter_alias(ty_substs, lt_substs, const_substs, || ty.clean(cx));
|
||||||
}
|
}
|
||||||
resolve_type(cx, path.clean(cx), self.id)
|
resolve_type(cx, path.clean(cx), self.id)
|
||||||
}
|
}
|
||||||
@ -3195,6 +3242,9 @@ impl Clean<GenericArgs> for hir::GenericArgs {
|
|||||||
GenericArg::Type(ty) => {
|
GenericArg::Type(ty) => {
|
||||||
types.push(ty.clean(cx));
|
types.push(ty.clean(cx));
|
||||||
}
|
}
|
||||||
|
GenericArg::Const(..) => {
|
||||||
|
unimplemented!() // FIXME(const_generics)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericArgs::AngleBracketed {
|
GenericArgs::AngleBracketed {
|
||||||
|
@ -65,6 +65,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
|
|||||||
pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
|
pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
|
||||||
/// Table `NodeId` of lifetime parameter definition -> substituted lifetime
|
/// Table `NodeId` of lifetime parameter definition -> substituted lifetime
|
||||||
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
|
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
|
||||||
|
/// Table node id of const parameter definition -> substituted const
|
||||||
|
pub ct_substs: RefCell<FxHashMap<Def, clean::Constant>>,
|
||||||
/// Table DefId of `impl Trait` in argument position -> bounds
|
/// Table DefId of `impl Trait` in argument position -> bounds
|
||||||
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
|
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
|
||||||
pub send_trait: Option<DefId>,
|
pub send_trait: Option<DefId>,
|
||||||
@ -85,14 +87,18 @@ impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
|
|||||||
pub fn enter_alias<F, R>(&self,
|
pub fn enter_alias<F, R>(&self,
|
||||||
ty_substs: FxHashMap<Def, clean::Type>,
|
ty_substs: FxHashMap<Def, clean::Type>,
|
||||||
lt_substs: FxHashMap<DefId, clean::Lifetime>,
|
lt_substs: FxHashMap<DefId, clean::Lifetime>,
|
||||||
|
ct_substs: FxHashMap<Def, clean::Constant>,
|
||||||
f: F) -> R
|
f: F) -> R
|
||||||
where F: FnOnce() -> R {
|
where F: FnOnce() -> R {
|
||||||
let (old_tys, old_lts) =
|
let (old_tys, old_lts, old_cts) = (
|
||||||
(mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs),
|
mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs),
|
||||||
mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs));
|
mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs),
|
||||||
|
mem::replace(&mut *self.ct_substs.borrow_mut(), ct_substs),
|
||||||
|
);
|
||||||
let r = f();
|
let r = f();
|
||||||
*self.ty_substs.borrow_mut() = old_tys;
|
*self.ty_substs.borrow_mut() = old_tys;
|
||||||
*self.lt_substs.borrow_mut() = old_lts;
|
*self.lt_substs.borrow_mut() = old_lts;
|
||||||
|
*self.ct_substs.borrow_mut() = old_cts;
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,6 +533,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
|||||||
renderinfo: RefCell::new(renderinfo),
|
renderinfo: RefCell::new(renderinfo),
|
||||||
ty_substs: Default::default(),
|
ty_substs: Default::default(),
|
||||||
lt_substs: Default::default(),
|
lt_substs: Default::default(),
|
||||||
|
ct_substs: Default::default(),
|
||||||
impl_trait_bounds: Default::default(),
|
impl_trait_bounds: Default::default(),
|
||||||
send_trait: send_trait,
|
send_trait: send_trait,
|
||||||
fake_def_ids: Default::default(),
|
fake_def_ids: Default::default(),
|
||||||
|
@ -138,6 +138,16 @@ impl fmt::Display for clean::GenericParamDef {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
clean::GenericParamDefKind::Const { ref ty, .. } => {
|
||||||
|
f.write_str("const ")?;
|
||||||
|
f.write_str(&self.name)?;
|
||||||
|
|
||||||
|
if f.alternate() {
|
||||||
|
write!(f, ": {:#}", ty)
|
||||||
|
} else {
|
||||||
|
write!(f, ": {}", ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1750,7 +1750,8 @@ impl<'a> Cache {
|
|||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
clean::GenericParamDefKind::Lifetime => {}
|
clean::GenericParamDefKind::Lifetime => {}
|
||||||
clean::GenericParamDefKind::Type { did, .. } => {
|
clean::GenericParamDefKind::Type { did, .. } |
|
||||||
|
clean::GenericParamDefKind::Const { did, .. } => {
|
||||||
self.typarams.insert(did, param.name.clone());
|
self.typarams.insert(did, param.name.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ fn foo<const X: (), T>(_: T) {
|
|||||||
|
|
||||||
fn bar<const X: (), 'a>(_: &'a ()) {
|
fn bar<const X: (), 'a>(_: &'a ()) {
|
||||||
//~^ ERROR lifetime parameters must be declared prior to const parameters
|
//~^ ERROR lifetime parameters must be declared prior to const parameters
|
||||||
|
//~^^ ERROR const generics in any position are currently unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -22,5 +22,11 @@ error: const generics in any position are currently unsupported
|
|||||||
LL | fn foo<const X: (), T>(_: T) {
|
LL | fn foo<const X: (), T>(_: T) {
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: const generics in any position are currently unsupported
|
||||||
|
--> $DIR/const-param-before-other-params.rs:9:14
|
||||||
|
|
|
||||||
|
LL | fn bar<const X: (), 'a>(_: &'a ()) {
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
#![feature(const_generics)]
|
||||||
|
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
|
||||||
|
#![deny(non_upper_case_globals)]
|
||||||
|
|
||||||
|
fn noop<const x: u32>() {
|
||||||
|
//~^ ERROR const generics in any position are currently unsupported
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||||
|
--> $DIR/const-parameter-uppercase-lint.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(const_generics)]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0601]: `main` function not found in crate `const_parameter_uppercase_lint`
|
||||||
|
|
|
||||||
|
= note: consider adding a `main` function to `$DIR/const-parameter-uppercase-lint.rs`
|
||||||
|
|
||||||
|
error: const generics in any position are currently unsupported
|
||||||
|
--> $DIR/const-parameter-uppercase-lint.rs:6:15
|
||||||
|
|
|
||||||
|
LL | fn noop<const x: u32>() {
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0601`.
|
@ -2,5 +2,6 @@ fn foo<const X: ()>() {} //~ ERROR const generics are unstable
|
|||||||
//~^ const generics in any position are currently unsupported
|
//~^ const generics in any position are currently unsupported
|
||||||
|
|
||||||
struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
|
struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
|
||||||
|
//~^ const generics in any position are currently unsupported
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -20,6 +20,12 @@ error: const generics in any position are currently unsupported
|
|||||||
LL | fn foo<const X: ()>() {} //~ ERROR const generics are unstable
|
LL | fn foo<const X: ()>() {} //~ ERROR const generics are unstable
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: const generics in any position are currently unsupported
|
||||||
|
--> $DIR/feature-gate-const_generics.rs:4:18
|
||||||
|
|
|
||||||
|
LL | struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#![deny(no_mangle_generic_items)]
|
#![deny(no_mangle_generic_items)]
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn foo<T>() {} //~ ERROR functions generic over types must be mangled
|
pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn bar<T>() {} //~ ERROR functions generic over types must be mangled
|
pub extern fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn baz(x: &i32) -> &i32 { x }
|
pub fn baz(x: &i32) -> &i32 { x }
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
error: functions generic over types must be mangled
|
error: functions generic over types or consts must be mangled
|
||||||
--> $DIR/generic-no-mangle.rs:4:1
|
--> $DIR/generic-no-mangle.rs:4:1
|
||||||
|
|
|
|
||||||
LL | #[no_mangle]
|
LL | #[no_mangle]
|
||||||
| ------------ help: remove this attribute
|
| ------------ help: remove this attribute
|
||||||
LL | pub fn foo<T>() {} //~ ERROR functions generic over types must be mangled
|
LL | pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
@ -12,12 +12,12 @@ note: lint level defined here
|
|||||||
LL | #![deny(no_mangle_generic_items)]
|
LL | #![deny(no_mangle_generic_items)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: functions generic over types must be mangled
|
error: functions generic over types or consts must be mangled
|
||||||
--> $DIR/generic-no-mangle.rs:7:1
|
--> $DIR/generic-no-mangle.rs:7:1
|
||||||
|
|
|
|
||||||
LL | #[no_mangle]
|
LL | #[no_mangle]
|
||||||
| ------------ help: remove this attribute
|
| ------------ help: remove this attribute
|
||||||
LL | pub extern fn bar<T>() {} //~ ERROR functions generic over types must be mangled
|
LL | pub extern fn bar<T>() {} //~ ERROR functions generic over types or consts must be mangled
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
//~^ HELP remove this attribute
|
//~^ HELP remove this attribute
|
||||||
pub fn defiant<T>(_t: T) {}
|
pub fn defiant<T>(_t: T) {}
|
||||||
//~^ WARN functions generic over types must be mangled
|
//~^ WARN functions generic over types or consts must be mangled
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn rio_grande() {}
|
fn rio_grande() {}
|
||||||
@ -23,7 +23,7 @@ mod badlands {
|
|||||||
//~^ ERROR const items should never be #[no_mangle]
|
//~^ ERROR const items should never be #[no_mangle]
|
||||||
//~| HELP try a static value
|
//~| HELP try a static value
|
||||||
#[no_mangle] pub fn val_jean<T>() {}
|
#[no_mangle] pub fn val_jean<T>() {}
|
||||||
//~^ WARN functions generic over types must be mangled
|
//~^ WARN functions generic over types or consts must be mangled
|
||||||
//~| HELP remove this attribute
|
//~| HELP remove this attribute
|
||||||
|
|
||||||
// ... but we can suggest just-`pub` instead of restricted
|
// ... but we can suggest just-`pub` instead of restricted
|
||||||
@ -31,7 +31,7 @@ mod badlands {
|
|||||||
//~^ ERROR const items should never be #[no_mangle]
|
//~^ ERROR const items should never be #[no_mangle]
|
||||||
//~| HELP try a static value
|
//~| HELP try a static value
|
||||||
#[no_mangle] pub(crate) fn crossfield<T>() {}
|
#[no_mangle] pub(crate) fn crossfield<T>() {}
|
||||||
//~^ WARN functions generic over types must be mangled
|
//~^ WARN functions generic over types or consts must be mangled
|
||||||
//~| HELP remove this attribute
|
//~| HELP remove this attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ LL | #[no_mangle] const DISCOVERY: usize = 1;
|
|||||||
|
|
|
|
||||||
= note: #[deny(no_mangle_const_items)] on by default
|
= note: #[deny(no_mangle_const_items)] on by default
|
||||||
|
|
||||||
warning: functions generic over types must be mangled
|
warning: functions generic over types or consts must be mangled
|
||||||
--> $DIR/suggestions.rs:12:1
|
--> $DIR/suggestions.rs:12:1
|
||||||
|
|
|
|
||||||
LL | #[no_mangle]
|
LL | #[no_mangle]
|
||||||
@ -73,7 +73,7 @@ LL | #[no_mangle] pub const DAUNTLESS: bool = true;
|
|||||||
| |
|
| |
|
||||||
| help: try a static value: `pub static`
|
| help: try a static value: `pub static`
|
||||||
|
|
||||||
warning: functions generic over types must be mangled
|
warning: functions generic over types or consts must be mangled
|
||||||
--> $DIR/suggestions.rs:25:18
|
--> $DIR/suggestions.rs:25:18
|
||||||
|
|
|
|
||||||
LL | #[no_mangle] pub fn val_jean<T>() {}
|
LL | #[no_mangle] pub fn val_jean<T>() {}
|
||||||
@ -89,7 +89,7 @@ LL | #[no_mangle] pub(crate) const VETAR: bool = true;
|
|||||||
| |
|
| |
|
||||||
| help: try a static value: `pub static`
|
| help: try a static value: `pub static`
|
||||||
|
|
||||||
warning: functions generic over types must be mangled
|
warning: functions generic over types or consts must be mangled
|
||||||
--> $DIR/suggestions.rs:33:18
|
--> $DIR/suggestions.rs:33:18
|
||||||
|
|
|
|
||||||
LL | #[no_mangle] pub(crate) fn crossfield<T>() {}
|
LL | #[no_mangle] pub(crate) fn crossfield<T>() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user