diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c516fbc3bb940..3034cacf6253f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1335,88 +1335,97 @@ pub fn checked_type_of<'a, 'tcx>( Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) | Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) | - Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) => { + Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) | + Node::TraitRef(..) => { let path = match parent_node { - Node::Ty(&hir::Ty { node: hir::TyKind::Path(ref path), .. }) | - Node::Expr(&hir::Expr { node: ExprKind::Path(ref path), .. }) => { - path + Node::Ty(&hir::Ty { + node: hir::TyKind::Path(QPath::Resolved(_, ref path)), + .. + }) + | Node::Expr(&hir::Expr { + node: ExprKind::Path(QPath::Resolved(_, ref path)), + .. + }) => { + Some(&**path) } Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => { - &*path + if let QPath::Resolved(_, ref path) = **path { + Some(&**path) + } else { + None + } } - _ => unreachable!(), + Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(path), + _ => None, }; - match path { - QPath::Resolved(_, ref path) => { - let arg_index = path.segments.iter() - .filter_map(|seg| seg.args.as_ref()) - .map(|generic_args| generic_args.args.as_ref()) - .find_map(|args| { - args.iter() - .filter(|arg| arg.is_const()) - .enumerate() - .filter(|(_, arg)| arg.id() == hir_id) - .map(|(index, _)| index) - .next() - }) - .or_else(|| { - if !fail { - None - } else { - bug!("no arg matching AnonConst in path") - } - })?; - - // We've encountered an `AnonConst` in some path, so we need to - // figure out which generic parameter it corresponds to and return - // the relevant type. - let generics = match path.res { - Res::Def(DefKind::Ctor(..), def_id) => - tcx.generics_of(tcx.parent(def_id).unwrap()), - Res::Def(_, def_id) => - tcx.generics_of(def_id), - Res::Err => - return Some(tcx.types.err), - _ if !fail => - return None, - x => { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "unexpected const parent path def {:?}", x - ), - ); - return Some(tcx.types.err); + if let Some(path) = path { + let arg_index = path.segments.iter() + .filter_map(|seg| seg.args.as_ref()) + .map(|generic_args| generic_args.args.as_ref()) + .find_map(|args| { + args.iter() + .filter(|arg| arg.is_const()) + .enumerate() + .filter(|(_, arg)| arg.id() == hir_id) + .map(|(index, _)| index) + .next() + }) + .or_else(|| { + if !fail { + None + } else { + bug!("no arg matching AnonConst in path") } - }; - - generics.params.iter() - .filter(|param| { - if let ty::GenericParamDefKind::Const = param.kind { - true - } else { - false - } - }) - .nth(arg_index) - .map(|param| tcx.type_of(param.def_id)) - // This is no generic parameter associated with the arg. This is - // probably from an extra arg where one is not needed. - .unwrap_or(tcx.types.err) - } - x => { - if !fail { - return None; + })?; + + // We've encountered an `AnonConst` in some path, so we need to + // figure out which generic parameter it corresponds to and return + // the relevant type. + let generics = match path.res { + Res::Def(DefKind::Ctor(..), def_id) => { + tcx.generics_of(tcx.parent(def_id).unwrap()) } - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "unexpected const parent path {:?}", x - ), - ); - tcx.types.err + Res::Def(_, def_id) => tcx.generics_of(def_id), + Res::Err => return Some(tcx.types.err), + _ if !fail => return None, + res => { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent path def {:?}", + res, + ), + ); + return Some(tcx.types.err); + } + }; + + generics.params.iter() + .filter(|param| { + if let ty::GenericParamDefKind::Const = param.kind { + true + } else { + false + } + }) + .nth(arg_index) + .map(|param| tcx.type_of(param.def_id)) + // This is no generic parameter associated with the arg. This is + // probably from an extra arg where one is not needed. + .unwrap_or(tcx.types.err) + } else { + if !fail { + return None; } + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "unexpected const parent path {:?}", + parent_node, + ), + ); + return Some(tcx.types.err); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f200d3ec8d5c1..671b313c7f24b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5244,9 +5244,13 @@ impl<'a> Parser<'a> { // FIXME(const_generics): to distinguish between idents for types and consts, // we should introduce a GenericArg::Ident in the AST and distinguish when // lowering to the HIR. For now, idents for const args are not permitted. - return Err( - self.fatal("identifiers may currently not be used for const generics") - ); + if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) { + self.parse_literal_maybe_minus()? + } else { + return Err( + self.fatal("identifiers may currently not be used for const generics") + ); + } } else { self.parse_literal_maybe_minus()? }; diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.rs b/src/test/ui/const-generics/condition-in-trait-const-arg.rs new file mode 100644 index 0000000000000..091fe904826d4 --- /dev/null +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.rs @@ -0,0 +1,12 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +trait IsZeroTrait{} + +impl IsZeroTrait<{0u8 == 0u8}> for () {} + +impl IsZeroTrait for ((),) {} + +fn main() {} diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.stderr b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr new file mode 100644 index 0000000000000..7c85651e7082f --- /dev/null +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/condition-in-trait-const-arg.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ +