Skip to content

Commit 4f2d183

Browse files
committed
Rework how type params are parsed
Separate lifetimes, type arguments, const params and type bindings as early as possible in the parser. When encountering bad ordering, suggest the correct order in a homogeneous way for all possible incorrect ordering.
1 parent 87ed0b4 commit 4f2d183

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+594
-561
lines changed

src/librustc/hir/intravisit.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -661,9 +661,11 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
661661
}
662662
}
663663

664-
pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
665-
path_span: Span,
666-
segment: &'v PathSegment) {
664+
pub fn walk_path_segment<'v, V: Visitor<'v>>(
665+
visitor: &mut V,
666+
path_span: Span,
667+
segment: &'v PathSegment,
668+
) {
667669
visitor.visit_ident(segment.ident);
668670
if let Some(id) = segment.hir_id {
669671
visitor.visit_id(id);
@@ -673,10 +675,12 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
673675
}
674676
}
675677

676-
pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V,
677-
_path_span: Span,
678-
generic_args: &'v GenericArgs) {
679-
walk_list!(visitor, visit_generic_arg, &generic_args.args);
678+
pub fn walk_generic_args<'v, V: Visitor<'v>>(
679+
visitor: &mut V,
680+
_path_span: Span,
681+
generic_args: &'v GenericArgs,
682+
) {
683+
walk_list!(visitor, visit_generic_arg, &generic_args.args);
680684
walk_list!(visitor, visit_assoc_type_binding, &generic_args.bindings);
681685
}
682686

src/librustc/hir/lowering.rs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,22 +1334,6 @@ impl<'a> LoweringContext<'a> {
13341334
}
13351335
}
13361336

1337-
fn lower_generic_arg(&mut self,
1338-
arg: &ast::GenericArg,
1339-
itctx: ImplTraitContext<'_>)
1340-
-> hir::GenericArg {
1341-
match arg {
1342-
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
1343-
ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
1344-
ast::GenericArg::Const(ct) => {
1345-
GenericArg::Const(ConstArg {
1346-
value: self.lower_anon_const(&ct),
1347-
span: ct.value.span,
1348-
})
1349-
}
1350-
}
1351-
}
1352-
13531337
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> P<hir::Ty> {
13541338
P(self.lower_ty_direct(t, itctx))
13551339
}
@@ -2175,17 +2159,25 @@ impl<'a> LoweringContext<'a> {
21752159
param_mode: ParamMode,
21762160
mut itctx: ImplTraitContext<'_>,
21772161
) -> (hir::GenericArgs, bool) {
2178-
let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
2179-
let has_types = args.iter().any(|arg| match arg {
2180-
ast::GenericArg::Type(_) => true,
2181-
_ => false,
2182-
});
2183-
(hir::GenericArgs {
2184-
args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(),
2185-
bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx.reborrow())).collect(),
2186-
parenthesized: false,
2187-
},
2188-
!has_types && param_mode == ParamMode::Optional)
2162+
let AngleBracketedArgs { lifetimes, types, const_args, bindings, .. } = &data;
2163+
let mut args = vec![];
2164+
for lt in lifetimes {
2165+
args.push(GenericArg::Lifetime(self.lower_lifetime(&lt)));
2166+
}
2167+
for ty in types {
2168+
args.push(GenericArg::Type(self.lower_ty_direct(&ty, itctx.reborrow())));
2169+
}
2170+
for ct in const_args {
2171+
args.push(GenericArg::Const(ConstArg {
2172+
value: self.lower_anon_const(&ct),
2173+
span: ct.value.span,
2174+
}))
2175+
}
2176+
let args = hir::HirVec::from(args);
2177+
let bindings = bindings.iter().map(|b| self.lower_ty_binding(b, itctx.reborrow()))
2178+
.collect();
2179+
(hir::GenericArgs { args, bindings, parenthesized: false },
2180+
types.is_empty() && param_mode == ParamMode::Optional)
21892181
}
21902182

21912183
fn lower_parenthesized_parameter_data(

src/librustc/ty/subst.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -549,21 +549,30 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
549549
fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
550550
// Look up the type in the substitutions. It really should be in there.
551551
let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack());
552+
debug!(
553+
"parameter `{:?}` ({:?}/{}), found {:?} when substituting (root type={:?}) substs={:?}",
554+
p,
555+
source_ty,
556+
p.index,
557+
opt_ty,
558+
self.root_ty,
559+
self.substs,
560+
);
552561
let ty = match opt_ty {
553562
Some(UnpackedKind::Type(ty)) => ty,
554563
Some(kind) => {
555564
let span = self.span.unwrap_or(DUMMY_SP);
556-
span_bug!(
557-
span,
558-
"expected type for `{:?}` ({:?}/{}) but found {:?} \
559-
when substituting (root type={:?}) substs={:?}",
565+
self.tcx.sess.delay_span_bug(span, &format!(
566+
"expected type for `{:?}` ({:?}/{}) but found {:?} when substituting \
567+
(root type={:?}) substs={:?}",
560568
p,
561569
source_ty,
562570
p.index,
563571
kind,
564572
self.root_ty,
565573
self.substs,
566-
);
574+
));
575+
self.tcx.types.err
567576
}
568577
None => {
569578
let span = self.span.unwrap_or(DUMMY_SP);

src/librustc_interface/util.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -712,11 +712,7 @@ impl<'a> ReplaceBodyWithLoop<'a> {
712712
match seg.args.as_ref().map(|generic_arg| &**generic_arg) {
713713
None => false,
714714
Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
715-
let types = data.args.iter().filter_map(|arg| match arg {
716-
ast::GenericArg::Type(ty) => Some(ty),
717-
_ => None,
718-
});
719-
any_involves_impl_trait(types.into_iter()) ||
715+
any_involves_impl_trait(data.types.iter()) ||
720716
any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty))
721717
},
722718
Some(&ast::GenericArgs::Parenthesized(ref data)) => {

src/librustc_passes/ast_validation.rs

Lines changed: 46 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use syntax::print::pprust;
1111
use rustc::lint;
1212
use rustc::lint::builtin::{BuiltinLintDiagnostics, NESTED_IMPL_TRAIT};
1313
use rustc::session::Session;
14-
use rustc_data_structures::fx::FxHashMap;
1514
use syntax::ast::*;
1615
use syntax::attr;
1716
use syntax::source_map::Spanned;
@@ -21,7 +20,7 @@ use syntax::visit::{self, Visitor};
2120
use syntax::{span_err, struct_span_err, walk_list};
2221
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
2322
use syntax_pos::{Span, MultiSpan};
24-
use errors::{Applicability, FatalError};
23+
use errors::Applicability;
2524
use log::debug;
2625

2726
#[derive(Copy, Clone, Debug)]
@@ -346,104 +345,65 @@ impl<'a> AstValidator<'a> {
346345
}
347346
}
348347

349-
enum GenericPosition {
350-
Param,
351-
Arg,
352-
}
353-
354348
fn validate_generics_order<'a>(
355-
sess: &Session,
356349
handler: &errors::Handler,
357350
generics: impl Iterator<
358-
Item = (
359-
ParamKindOrd,
360-
Option<&'a [GenericBound]>,
361-
Span,
362-
Option<String>
363-
),
351+
Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>),
364352
>,
365-
pos: GenericPosition,
366353
span: Span,
367354
) {
368-
let mut max_param: Option<ParamKindOrd> = None;
369-
let mut out_of_order = FxHashMap::default();
370-
let mut param_idents = vec![];
371-
let mut found_type = false;
372-
let mut found_const = false;
373-
374-
for (kind, bounds, span, ident) in generics {
375-
if let Some(ident) = ident {
376-
param_idents.push((kind, bounds, param_idents.len(), ident));
377-
}
378-
let max_param = &mut max_param;
379-
match max_param {
380-
Some(max_param) if *max_param > kind => {
381-
let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
382-
entry.1.push(span);
383-
}
384-
Some(_) | None => *max_param = Some(kind),
355+
let mut lifetimes = vec![];
356+
let mut type_args = vec![];
357+
let mut const_args = vec![];
358+
let mut out_of_order = false;
359+
360+
for (kind, bounds, _span, ident) in generics {
361+
let ident = match ident {
362+
Some(ident) => ident,
363+
None => return,
385364
};
386365
match kind {
387-
ParamKindOrd::Type => found_type = true,
388-
ParamKindOrd::Const => found_const = true,
389-
_ => {}
366+
ParamKindOrd::Lifetime => {
367+
lifetimes.push((ident, bounds));
368+
out_of_order |= type_args.len() > 0 || const_args.len() > 0;
369+
}
370+
ParamKindOrd::Type => {
371+
type_args.push((ident, bounds));
372+
out_of_order |= const_args.len() > 0;
373+
}
374+
ParamKindOrd::Const => {
375+
const_args.push((ident, bounds));
376+
}
390377
}
391378
}
379+
if !out_of_order {
380+
return;
381+
}
392382

393383
let mut ordered_params = "<".to_string();
394-
if !out_of_order.is_empty() {
395-
param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
396-
let mut first = true;
397-
for (_, bounds, _, ident) in param_idents {
398-
if !first {
399-
ordered_params += ", ";
400-
}
401-
ordered_params += &ident;
402-
if let Some(bounds) = bounds {
403-
if !bounds.is_empty() {
404-
ordered_params += ": ";
405-
ordered_params += &pprust::bounds_to_string(&bounds);
406-
}
384+
let mut first = true;
385+
for (ident, bounds) in lifetimes.iter().chain(type_args.iter()).chain(const_args.iter()) {
386+
if !first {
387+
ordered_params += ", ";
388+
}
389+
ordered_params += &ident;
390+
if let Some(bounds) = bounds {
391+
if !bounds.is_empty() {
392+
ordered_params += ": ";
393+
ordered_params += &pprust::bounds_to_string(&bounds);
407394
}
408-
first = false;
409395
}
396+
first = false;
410397
}
411398
ordered_params += ">";
412399

413-
let pos_str = match pos {
414-
GenericPosition::Param => "parameter",
415-
GenericPosition::Arg => "argument",
416-
};
417-
418-
for (param_ord, (max_param, spans)) in &out_of_order {
419-
let mut err = handler.struct_span_err(spans.clone(),
420-
&format!(
421-
"{} {pos}s must be declared prior to {} {pos}s",
422-
param_ord,
423-
max_param,
424-
pos = pos_str,
425-
));
426-
if let GenericPosition::Param = pos {
427-
err.span_suggestion(
428-
span,
429-
&format!(
430-
"reorder the {}s: lifetimes, then types{}",
431-
pos_str,
432-
if sess.features_untracked().const_generics { ", then consts" } else { "" },
433-
),
434-
ordered_params.clone(),
435-
Applicability::MachineApplicable,
436-
);
437-
}
438-
err.emit();
439-
}
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-
}
400+
handler.struct_span_err(span, "incorrect parameter order")
401+
.span_suggestion(
402+
span,
403+
"reorder the parameters",
404+
ordered_params.clone(),
405+
Applicability::MachineApplicable,
406+
).emit();
447407
}
448408

449409
impl<'a> Visitor<'a> for AstValidator<'a> {
@@ -703,21 +663,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
703663
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
704664
match *generic_args {
705665
GenericArgs::AngleBracketed(ref data) => {
706-
walk_list!(self, visit_generic_arg, &data.args);
707-
validate_generics_order(
708-
self.session,
709-
self.err_handler(),
710-
data.args.iter().map(|arg| {
711-
(match arg {
712-
GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
713-
GenericArg::Type(..) => ParamKindOrd::Type,
714-
GenericArg::Const(..) => ParamKindOrd::Const,
715-
}, None, arg.span(), None)
716-
}),
717-
GenericPosition::Arg,
718-
generic_args.span(),
719-
);
720-
666+
walk_list!(self, visit_lifetime, &data.lifetimes);
667+
walk_list!(self, visit_ty, &data.types);
668+
walk_list!(self, visit_anon_const, &data.const_args);
721669
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
722670
// are allowed to contain nested `impl Trait`.
723671
self.with_impl_trait(None, |this| {
@@ -750,7 +698,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
750698
}
751699

752700
validate_generics_order(
753-
self.session,
754701
self.err_handler(),
755702
generics.params.iter().map(|param| {
756703
let ident = Some(param.ident.to_string());
@@ -764,7 +711,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
764711
};
765712
(kind, Some(&*param.bounds), param.ident.span, ident)
766713
}),
767-
GenericPosition::Param,
768714
generics.span,
769715
);
770716

src/librustc_save_analysis/dump_visitor.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -795,11 +795,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
795795
if let Some(ref generic_args) = seg.args {
796796
match **generic_args {
797797
ast::GenericArgs::AngleBracketed(ref data) => {
798-
for arg in &data.args {
799-
match arg {
800-
ast::GenericArg::Type(ty) => self.visit_ty(ty),
801-
_ => {}
802-
}
798+
for ty in &data.types {
799+
self.visit_ty(ty);
803800
}
804801
}
805802
ast::GenericArgs::Parenthesized(ref data) => {
@@ -861,11 +858,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
861858
// Explicit types in the turbo-fish.
862859
if let Some(ref generic_args) = seg.args {
863860
if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
864-
for arg in &data.args {
865-
match arg {
866-
ast::GenericArg::Type(ty) => self.visit_ty(ty),
867-
_ => {}
868-
}
861+
for ty in &data.types {
862+
self.visit_ty(ty);
869863
}
870864
}
871865
}

0 commit comments

Comments
 (0)