Skip to content

Commit c236c24

Browse files
varkoryodaldevoid
andcommitted
Handle const generics in typeck
Co-Authored-By: Gabriel Smith <[email protected]>
1 parent 8e56729 commit c236c24

File tree

10 files changed

+87
-17
lines changed

10 files changed

+87
-17
lines changed

src/librustc_typeck/check/closure.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9999
let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| {
100100
match param.kind {
101101
GenericParamDefKind::Lifetime => {
102-
span_bug!(expr.span, "closure has region param")
102+
span_bug!(expr.span, "closure has lifetime param")
103103
}
104-
GenericParamDefKind::Type {..} => {
105-
self.infcx
106-
.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)).into()
104+
GenericParamDefKind::Type { .. } => {
105+
self.infcx.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)).into()
106+
}
107+
GenericParamDefKind::Const => {
108+
span_bug!(expr.span, "closure has const param")
107109
}
108110
}
109111
});

src/librustc_typeck/check/dropck.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
313313
match kind.unpack() {
314314
UnpackedKind::Lifetime(r) => rcx.sub_regions(origin(), parent_scope, r),
315315
UnpackedKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope),
316+
UnpackedKind::Const(_) => {
317+
// Generic consts don't add constraints.
318+
}
316319
}
317320
}
318321
Ok(())

src/librustc_typeck/check/method/confirm.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
341341
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
342342
self.to_ty(ty).into()
343343
}
344+
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
345+
self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into()
346+
}
344347
_ => unreachable!(),
345348
}
346349
},

src/librustc_typeck/check/method/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
283283
// Construct a trait-reference `self_ty : Trait<input_tys>`
284284
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
285285
match param.kind {
286-
GenericParamDefKind::Lifetime => {}
287-
GenericParamDefKind::Type {..} => {
286+
GenericParamDefKind::Lifetime | GenericParamDefKind::Const => {}
287+
GenericParamDefKind::Type { .. } => {
288288
if param.index == 0 {
289289
return self_ty.into();
290290
} else if let Some(ref input_types) = opt_input_types {

src/librustc_typeck/check/method/probe.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
15281528
// `impl_self_ty()` for an explanation.
15291529
self.tcx.types.re_erased.into()
15301530
}
1531-
GenericParamDefKind::Type {..} => self.var_for_def(self.span, param),
1531+
GenericParamDefKind::Type { .. }
1532+
| GenericParamDefKind::Const => {
1533+
self.var_for_def(self.span, param)
1534+
}
15321535
}
15331536
}
15341537
});
@@ -1545,10 +1548,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
15451548
InternalSubsts::for_item(self.tcx, def_id, |param, _| {
15461549
match param.kind {
15471550
GenericParamDefKind::Lifetime => self.tcx.types.re_erased.into(),
1548-
GenericParamDefKind::Type {..} => {
1551+
GenericParamDefKind::Type { .. } => {
15491552
self.next_ty_var(TypeVariableOrigin::SubstitutionPlaceholder(
15501553
self.tcx.def_span(def_id))).into()
15511554
}
1555+
GenericParamDefKind::Const { .. } => {
1556+
unimplemented!() // FIXME(const_generics)
1557+
}
15521558
}
15531559
})
15541560
}

src/librustc_typeck/check/mod.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24372437
ty
24382438
}
24392439

2440+
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
2441+
AstConv::ast_const_to_const(self, ast_c, ty)
2442+
}
2443+
24402444
// If the type given by the user has free regions, save it for later, since
24412445
// NLL would like to enforce those. Also pass in types that involve
24422446
// projections, since those can resolve to `'static` bounds (modulo #54940,
@@ -5501,6 +5505,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
55015505
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
55025506
self.to_ty(ty).into()
55035507
}
5508+
(GenericParamDefKind::Const, GenericArg::Const(ct)) => {
5509+
self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into()
5510+
}
55045511
_ => unreachable!(),
55055512
}
55065513
},
@@ -5528,6 +5535,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
55285535
self.var_for_def(span, param)
55295536
}
55305537
}
5538+
GenericParamDefKind::Const => {
5539+
// FIXME(const_generics:defaults)
5540+
// No const parameters were provided, we have to infer them.
5541+
self.var_for_def(span, param)
5542+
}
55315543
}
55325544
},
55335545
);
@@ -5685,11 +5697,19 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
56855697
generics: &ty::Generics,
56865698
ty: Ty<'tcx>) {
56875699
let own_counts = generics.own_counts();
5688-
debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
5700+
debug!(
5701+
"check_bounds_are_used(n_tys={}, n_cts={}, ty={:?})",
5702+
own_counts.types,
5703+
own_counts.consts,
5704+
ty
5705+
);
5706+
5707+
// FIXME(const_generics): we probably want to check the bounds for const parameters too.
56895708

56905709
if own_counts.types == 0 {
56915710
return;
56925711
}
5712+
56935713
// Make a vector of booleans initially false, set to true when used.
56945714
let mut types_used = vec![false; own_counts.types];
56955715

src/librustc_typeck/constrained_type_params.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc::ty::{self, Ty, TyCtxt};
22
use rustc::ty::fold::{TypeFoldable, TypeVisitor};
33
use rustc::util::nodemap::FxHashSet;
4+
use rustc::mir::interpret::ConstValue;
45
use syntax::source_map::Span;
56

67
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
@@ -14,6 +15,10 @@ impl From<ty::EarlyBoundRegion> for Parameter {
1415
fn from(param: ty::EarlyBoundRegion) -> Self { Parameter(param.index) }
1516
}
1617

18+
impl From<ty::ParamConst> for Parameter {
19+
fn from(param: ty::ParamConst) -> Self { Parameter(param.index) }
20+
}
21+
1722
/// Returns the set of parameters constrained by the impl header.
1823
pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>,
1924
impl_trait_ref: Option<ty::TraitRef<'tcx>>)
@@ -72,6 +77,16 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
7277
}
7378
false
7479
}
80+
81+
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
82+
if let ty::LazyConst::Evaluated(ty::Const {
83+
val: ConstValue::Param(data),
84+
..
85+
}) = c {
86+
self.parameters.push(Parameter::from(*data));
87+
}
88+
false
89+
}
7590
}
7691

7792
pub fn identify_constrained_type_params<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,

src/librustc_typeck/impl_wf_check.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
120120
for param in &impl_generics.params {
121121
match param.kind {
122122
// Disallow ANY unconstrained type parameters.
123-
ty::GenericParamDefKind::Type {..} => {
123+
ty::GenericParamDefKind::Type { .. } => {
124124
let param_ty = ty::ParamTy::for_def(param);
125125
if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
126126
report_unused_parameter(tcx,
@@ -139,6 +139,15 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
139139
&param.name.to_string());
140140
}
141141
}
142+
ty::GenericParamDefKind::Const => {
143+
let param_ct = ty::ParamConst::for_def(param);
144+
if !input_parameters.contains(&ctp::Parameter::from(param_ct)) {
145+
report_unused_parameter(tcx,
146+
tcx.def_span(param.def_id),
147+
"const",
148+
&param_ct.to_string());
149+
}
150+
}
142151
}
143152
}
144153

src/librustc_typeck/outlives/mod.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,22 @@ fn inferred_outlives_crate<'tcx>(
9898
.map(|(&def_id, set)| {
9999
let vec: Vec<ty::Predicate<'tcx>> = set
100100
.iter()
101-
.map(
101+
.filter_map(
102102
|ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
103-
UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder::bind(
104-
ty::OutlivesPredicate(ty1, region2),
105-
)),
106-
UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives(
107-
ty::Binder::bind(ty::OutlivesPredicate(region1, region2)),
108-
),
103+
UnpackedKind::Type(ty1) => {
104+
Some(ty::Predicate::TypeOutlives(ty::Binder::bind(
105+
ty::OutlivesPredicate(ty1, region2)
106+
)))
107+
}
108+
UnpackedKind::Lifetime(region1) => {
109+
Some(ty::Predicate::RegionOutlives(
110+
ty::Binder::bind(ty::OutlivesPredicate(region1, region2))
111+
))
112+
}
113+
UnpackedKind::Const(_) => {
114+
// Generic consts don't impose any constraints.
115+
None
116+
}
109117
},
110118
).collect();
111119
(def_id, Lrc::new(vec))

src/librustc_typeck/outlives/utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ pub fn insert_outlives_predicate<'tcx>(
118118
}
119119
required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
120120
}
121+
122+
UnpackedKind::Const(_) => {
123+
// Generic consts don't impose any constraints.
124+
}
121125
}
122126
}
123127

0 commit comments

Comments
 (0)