Auto merge of #60508 - varkor:const-generics-fold-ct-err, r=petrochenkov

Fix substs issues for const errors

Fixes https://github.com/rust-lang/rust/issues/60503.
This commit is contained in:
bors 2019-05-05 03:39:16 +00:00
commit c55b68aaef
10 changed files with 107 additions and 37 deletions

View File

@ -550,17 +550,32 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack());
let ty = match opt_ty {
Some(UnpackedKind::Type(ty)) => ty,
_ => {
Some(kind) => {
let span = self.span.unwrap_or(DUMMY_SP);
span_bug!(
span,
"Type parameter `{:?}` ({:?}/{}) out of range \
"expected type for `{:?}` ({:?}/{}) but found {:?} \
when substituting (root type={:?}) substs={:?}",
p,
source_ty,
p.idx,
kind,
self.root_ty,
self.substs,
);
}
None => {
let span = self.span.unwrap_or(DUMMY_SP);
span_bug!(
span,
"type parameter `{:?}` ({:?}/{}) out of range \
when substituting (root type={:?}) substs={:?}",
p,
source_ty,
p.idx,
self.root_ty,
self.substs);
self.substs,
);
}
};
@ -570,29 +585,41 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
fn const_for_param(
&self,
p: ParamConst,
source_cn: &'tcx ty::Const<'tcx>
source_ct: &'tcx ty::Const<'tcx>
) -> &'tcx ty::Const<'tcx> {
// Look up the const in the substitutions. It really should be in there.
let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
let cn = match opt_cn {
Some(UnpackedKind::Const(cn)) => cn,
_ => {
let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack());
let ct = match opt_ct {
Some(UnpackedKind::Const(ct)) => ct,
Some(kind) => {
let span = self.span.unwrap_or(DUMMY_SP);
span_bug!(
span,
"Const parameter `{:?}` ({:?}/{}) out of range \
when substituting (root type={:?}) substs={:?}",
"expected const for `{:?}` ({:?}/{}) but found {:?} \
when substituting substs={:?}",
p,
source_cn,
source_ct,
p.index,
kind,
self.substs,
);
}
None => {
let span = self.span.unwrap_or(DUMMY_SP);
span_bug!(
span,
"const parameter `{:?}` ({:?}/{}) out of range \
when substituting substs={:?}",
p,
source_ct,
p.index,
self.root_ty,
self.substs,
);
}
};
// FIXME(const_generics): shift const through binders
cn
ct
}
/// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs

View File

@ -21,7 +21,7 @@ use syntax::visit::{self, Visitor};
use syntax::{span_err, struct_span_err, walk_list};
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
use syntax_pos::{Span, MultiSpan};
use errors::Applicability;
use errors::{Applicability, FatalError};
use log::debug;
#[derive(Copy, Clone, Debug)]
@ -368,6 +368,8 @@ fn validate_generics_order<'a>(
let mut max_param: Option<ParamKindOrd> = None;
let mut out_of_order = FxHashMap::default();
let mut param_idents = vec![];
let mut found_type = false;
let mut found_const = false;
for (kind, bounds, span, ident) in generics {
if let Some(ident) = ident {
@ -381,6 +383,11 @@ fn validate_generics_order<'a>(
}
Some(_) | None => *max_param = Some(kind),
};
match kind {
ParamKindOrd::Type => found_type = true,
ParamKindOrd::Const => found_const = true,
_ => {}
}
}
let mut ordered_params = "<".to_string();
@ -408,8 +415,8 @@ fn validate_generics_order<'a>(
GenericPosition::Arg => "argument",
};
for (param_ord, (max_param, spans)) in out_of_order {
let mut err = handler.struct_span_err(spans,
for (param_ord, (max_param, spans)) in &out_of_order {
let mut err = handler.struct_span_err(spans.clone(),
&format!(
"{} {pos}s must be declared prior to {} {pos}s",
param_ord,
@ -430,6 +437,13 @@ fn validate_generics_order<'a>(
}
err.emit();
}
// FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
// if we don't. Const parameters and type parameters can currently conflict if they
// are out-of-order.
if !out_of_order.is_empty() && found_type && found_const {
FatalError.raise();
}
}
impl<'a> Visitor<'a> for AstValidator<'a> {

View File

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

View File

@ -421,8 +421,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
return_ty: Option<Ty<'tcx>>,
) {
let predicates = fcx.tcx.predicates_of(def_id);
let generics = tcx.generics_of(def_id);
let is_our_default = |def: &ty::GenericParamDef| {
match def.kind {
GenericParamDefKind::Type { has_default, .. } => {
@ -465,6 +465,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
// All regions are identity.
fcx.tcx.mk_param_from_def(param)
}
GenericParamDefKind::Type { .. } => {
// If the param has a default,
if is_our_default(param) {
@ -478,25 +479,24 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
// Mark unwanted params as err.
fcx.tcx.types.err.into()
}
GenericParamDefKind::Const => {
// FIXME(const_generics:defaults)
fcx.tcx.types.err.into()
fcx.tcx.consts.err.into()
}
}
});
// Now we build the substituted predicates.
let default_obligations = predicates.predicates.iter().flat_map(|&(pred, _)| {
#[derive(Default)]
struct CountParams { params: FxHashSet<u32> }
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
match t.sty {
ty::Param(p) => {
self.params.insert(p.idx);
t.super_visit_with(self)
}
_ => t.super_visit_with(self)
if let ty::Param(param) = t.sty {
self.params.insert(param.idx);
}
t.super_visit_with(self)
}
fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {

View File

@ -1,12 +1,12 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn foo<const X: (), T>(_: &T) {
//~^ ERROR type parameters must be declared prior to const parameters
}
fn bar<const X: (), 'a>(_: &'a ()) {
//~^ ERROR lifetime parameters must be declared prior to const parameters
}
fn foo<const X: (), T>(_: &T) {
//~^ ERROR type parameters must be declared prior to const parameters
}
fn main() {}

View File

@ -4,17 +4,17 @@ warning: the feature `const_generics` is incomplete and may cause the compiler t
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
error: type parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:4:21
|
LL | fn foo<const X: (), T>(_: &T) {
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
error: lifetime parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:8:21
--> $DIR/const-param-before-other-params.rs:4:21
|
LL | fn bar<const X: (), 'a>(_: &'a ()) {
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
error: type parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:8:21
|
LL | fn foo<const X: (), T>(_: &T) {
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
error: aborting due to 2 previous errors

View File

@ -0,0 +1,3 @@
trait Trait<const T: ()> {} //~ ERROR const generics are unstable
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0658]: const generics are unstable
--> $DIR/const-param-in-trait-ungated.rs:1:19
|
LL | trait Trait<const T: ()> {}
| ^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
= help: add #![feature(const_generics)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,8 @@
// run-pass
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
trait Trait<const T: ()> {}
fn main() {}

View File

@ -0,0 +1,6 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/const-param-in-trait.rs:3:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^