Skip to content

Commit c55b68a

Browse files
committed
Auto merge of #60508 - varkor:const-generics-fold-ct-err, r=petrochenkov
Fix substs issues for const errors Fixes #60503.
2 parents a823fa4 + 3e6787c commit c55b68a

10 files changed

+106
-36
lines changed

src/librustc/ty/subst.rs

+40-13
Original file line numberDiff line numberDiff line change
@@ -550,17 +550,32 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
550550
let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack());
551551
let ty = match opt_ty {
552552
Some(UnpackedKind::Type(ty)) => ty,
553-
_ => {
553+
Some(kind) => {
554554
let span = self.span.unwrap_or(DUMMY_SP);
555555
span_bug!(
556556
span,
557-
"Type parameter `{:?}` ({:?}/{}) out of range \
557+
"expected type for `{:?}` ({:?}/{}) but found {:?} \
558558
when substituting (root type={:?}) substs={:?}",
559559
p,
560560
source_ty,
561561
p.idx,
562+
kind,
562563
self.root_ty,
563-
self.substs);
564+
self.substs,
565+
);
566+
}
567+
None => {
568+
let span = self.span.unwrap_or(DUMMY_SP);
569+
span_bug!(
570+
span,
571+
"type parameter `{:?}` ({:?}/{}) out of range \
572+
when substituting (root type={:?}) substs={:?}",
573+
p,
574+
source_ty,
575+
p.idx,
576+
self.root_ty,
577+
self.substs,
578+
);
564579
}
565580
};
566581

@@ -570,29 +585,41 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
570585
fn const_for_param(
571586
&self,
572587
p: ParamConst,
573-
source_cn: &'tcx ty::Const<'tcx>
588+
source_ct: &'tcx ty::Const<'tcx>
574589
) -> &'tcx ty::Const<'tcx> {
575590
// Look up the const in the substitutions. It really should be in there.
576-
let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
577-
let cn = match opt_cn {
578-
Some(UnpackedKind::Const(cn)) => cn,
579-
_ => {
591+
let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack());
592+
let ct = match opt_ct {
593+
Some(UnpackedKind::Const(ct)) => ct,
594+
Some(kind) => {
580595
let span = self.span.unwrap_or(DUMMY_SP);
581596
span_bug!(
582597
span,
583-
"Const parameter `{:?}` ({:?}/{}) out of range \
584-
when substituting (root type={:?}) substs={:?}",
598+
"expected const for `{:?}` ({:?}/{}) but found {:?} \
599+
when substituting substs={:?}",
585600
p,
586-
source_cn,
601+
source_ct,
602+
p.index,
603+
kind,
604+
self.substs,
605+
);
606+
}
607+
None => {
608+
let span = self.span.unwrap_or(DUMMY_SP);
609+
span_bug!(
610+
span,
611+
"const parameter `{:?}` ({:?}/{}) out of range \
612+
when substituting substs={:?}",
613+
p,
614+
source_ct,
587615
p.index,
588-
self.root_ty,
589616
self.substs,
590617
);
591618
}
592619
};
593620

594621
// FIXME(const_generics): shift const through binders
595-
cn
622+
ct
596623
}
597624

598625
/// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs

src/librustc_passes/ast_validation.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use syntax::visit::{self, Visitor};
2121
use syntax::{span_err, struct_span_err, walk_list};
2222
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
2323
use syntax_pos::{Span, MultiSpan};
24-
use errors::Applicability;
24+
use errors::{Applicability, FatalError};
2525
use log::debug;
2626

2727
#[derive(Copy, Clone, Debug)]
@@ -368,6 +368,8 @@ fn validate_generics_order<'a>(
368368
let mut max_param: Option<ParamKindOrd> = None;
369369
let mut out_of_order = FxHashMap::default();
370370
let mut param_idents = vec![];
371+
let mut found_type = false;
372+
let mut found_const = false;
371373

372374
for (kind, bounds, span, ident) in generics {
373375
if let Some(ident) = ident {
@@ -381,6 +383,11 @@ fn validate_generics_order<'a>(
381383
}
382384
Some(_) | None => *max_param = Some(kind),
383385
};
386+
match kind {
387+
ParamKindOrd::Type => found_type = true,
388+
ParamKindOrd::Const => found_const = true,
389+
_ => {}
390+
}
384391
}
385392

386393
let mut ordered_params = "<".to_string();
@@ -408,8 +415,8 @@ fn validate_generics_order<'a>(
408415
GenericPosition::Arg => "argument",
409416
};
410417

411-
for (param_ord, (max_param, spans)) in out_of_order {
412-
let mut err = handler.struct_span_err(spans,
418+
for (param_ord, (max_param, spans)) in &out_of_order {
419+
let mut err = handler.struct_span_err(spans.clone(),
413420
&format!(
414421
"{} {pos}s must be declared prior to {} {pos}s",
415422
param_ord,
@@ -430,6 +437,13 @@ fn validate_generics_order<'a>(
430437
}
431438
err.emit();
432439
}
440+
441+
// FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
442+
// if we don't. Const parameters and type parameters can currently conflict if they
443+
// are out-of-order.
444+
if !out_of_order.is_empty() && found_type && found_const {
445+
FatalError.raise();
446+
}
433447
}
434448

435449
impl<'a> Visitor<'a> for AstValidator<'a> {

src/librustc_typeck/astconv.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
553553
tcx.intern_substs(&substs)
554554
}
555555

556-
/// Given the type/region arguments provided to some path (along with
556+
/// Given the type/lifetime/const arguments provided to some path (along with
557557
/// an implicit `Self`, if this is a trait reference) returns the complete
558558
/// set of substitutions. This may involve applying defaulted type parameters.
559559
///
@@ -678,7 +678,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
678678
GenericParamDefKind::Const => {
679679
// FIXME(const_generics:defaults)
680680
// We've already errored above about the mismatch.
681-
tcx.types.err.into()
681+
tcx.consts.err.into()
682682
}
683683
}
684684
},

src/librustc_typeck/check/wfcheck.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
421421
return_ty: Option<Ty<'tcx>>,
422422
) {
423423
let predicates = fcx.tcx.predicates_of(def_id);
424-
425424
let generics = tcx.generics_of(def_id);
425+
426426
let is_our_default = |def: &ty::GenericParamDef| {
427427
match def.kind {
428428
GenericParamDefKind::Type { has_default, .. } => {
@@ -465,6 +465,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
465465
// All regions are identity.
466466
fcx.tcx.mk_param_from_def(param)
467467
}
468+
468469
GenericParamDefKind::Type { .. } => {
469470
// If the param has a default,
470471
if is_our_default(param) {
@@ -478,25 +479,24 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
478479
// Mark unwanted params as err.
479480
fcx.tcx.types.err.into()
480481
}
482+
481483
GenericParamDefKind::Const => {
482484
// FIXME(const_generics:defaults)
483-
fcx.tcx.types.err.into()
485+
fcx.tcx.consts.err.into()
484486
}
485487
}
486488
});
489+
487490
// Now we build the substituted predicates.
488491
let default_obligations = predicates.predicates.iter().flat_map(|&(pred, _)| {
489492
#[derive(Default)]
490493
struct CountParams { params: FxHashSet<u32> }
491494
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
492495
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
493-
match t.sty {
494-
ty::Param(p) => {
495-
self.params.insert(p.idx);
496-
t.super_visit_with(self)
497-
}
498-
_ => t.super_visit_with(self)
496+
if let ty::Param(param) = t.sty {
497+
self.params.insert(param.idx);
499498
}
499+
t.super_visit_with(self)
500500
}
501501

502502
fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#![feature(const_generics)]
22
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
33

4-
fn foo<const X: (), T>(_: &T) {
5-
//~^ ERROR type parameters must be declared prior to const parameters
6-
}
7-
84
fn bar<const X: (), 'a>(_: &'a ()) {
95
//~^ ERROR lifetime parameters must be declared prior to const parameters
106
}
117

8+
fn foo<const X: (), T>(_: &T) {
9+
//~^ ERROR type parameters must be declared prior to const parameters
10+
}
11+
1212
fn main() {}

src/test/ui/const-generics/const-param-before-other-params.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t
44
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66

7-
error: type parameters must be declared prior to const parameters
7+
error: lifetime parameters must be declared prior to const parameters
88
--> $DIR/const-param-before-other-params.rs:4:21
99
|
10-
LL | fn foo<const X: (), T>(_: &T) {
11-
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
10+
LL | fn bar<const X: (), 'a>(_: &'a ()) {
11+
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
1212

13-
error: lifetime parameters must be declared prior to const parameters
13+
error: type parameters must be declared prior to const parameters
1414
--> $DIR/const-param-before-other-params.rs:8:21
1515
|
16-
LL | fn bar<const X: (), 'a>(_: &'a ()) {
17-
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
16+
LL | fn foo<const X: (), T>(_: &T) {
17+
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
1818

1919
error: aborting due to 2 previous errors
2020

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trait Trait<const T: ()> {} //~ ERROR const generics are unstable
2+
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: const generics are unstable
2+
--> $DIR/const-param-in-trait-ungated.rs:1:19
3+
|
4+
LL | trait Trait<const T: ()> {}
5+
| ^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
8+
= help: add #![feature(const_generics)] to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-pass
2+
3+
#![feature(const_generics)]
4+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
5+
6+
trait Trait<const T: ()> {}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/const-param-in-trait.rs:3:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+

0 commit comments

Comments
 (0)