Skip to content

Commit b162ccc

Browse files
authored
Rollup merge of rust-lang#61409 - varkor:condition-trait-param-ice, r=oli-obk
Fix an ICE with a const argument in a trait This goes some way towards fixing rust-lang#61383 (the reduced test case is fixed).
2 parents 5c6b7ac + 2b27c62 commit b162ccc

File tree

4 files changed

+107
-76
lines changed

4 files changed

+107
-76
lines changed

src/librustc_typeck/collect.rs

+82-73
Original file line numberDiff line numberDiff line change
@@ -1335,88 +1335,97 @@ pub fn checked_type_of<'a, 'tcx>(
13351335

13361336
Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) |
13371337
Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) |
1338-
Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) => {
1338+
Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) |
1339+
Node::TraitRef(..) => {
13391340
let path = match parent_node {
1340-
Node::Ty(&hir::Ty { node: hir::TyKind::Path(ref path), .. }) |
1341-
Node::Expr(&hir::Expr { node: ExprKind::Path(ref path), .. }) => {
1342-
path
1341+
Node::Ty(&hir::Ty {
1342+
node: hir::TyKind::Path(QPath::Resolved(_, ref path)),
1343+
..
1344+
})
1345+
| Node::Expr(&hir::Expr {
1346+
node: ExprKind::Path(QPath::Resolved(_, ref path)),
1347+
..
1348+
}) => {
1349+
Some(&**path)
13431350
}
13441351
Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => {
1345-
&*path
1352+
if let QPath::Resolved(_, ref path) = **path {
1353+
Some(&**path)
1354+
} else {
1355+
None
1356+
}
13461357
}
1347-
_ => unreachable!(),
1358+
Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(path),
1359+
_ => None,
13481360
};
13491361

1350-
match path {
1351-
QPath::Resolved(_, ref path) => {
1352-
let arg_index = path.segments.iter()
1353-
.filter_map(|seg| seg.args.as_ref())
1354-
.map(|generic_args| generic_args.args.as_ref())
1355-
.find_map(|args| {
1356-
args.iter()
1357-
.filter(|arg| arg.is_const())
1358-
.enumerate()
1359-
.filter(|(_, arg)| arg.id() == hir_id)
1360-
.map(|(index, _)| index)
1361-
.next()
1362-
})
1363-
.or_else(|| {
1364-
if !fail {
1365-
None
1366-
} else {
1367-
bug!("no arg matching AnonConst in path")
1368-
}
1369-
})?;
1370-
1371-
// We've encountered an `AnonConst` in some path, so we need to
1372-
// figure out which generic parameter it corresponds to and return
1373-
// the relevant type.
1374-
let generics = match path.res {
1375-
Res::Def(DefKind::Ctor(..), def_id) =>
1376-
tcx.generics_of(tcx.parent(def_id).unwrap()),
1377-
Res::Def(_, def_id) =>
1378-
tcx.generics_of(def_id),
1379-
Res::Err =>
1380-
return Some(tcx.types.err),
1381-
_ if !fail =>
1382-
return None,
1383-
x => {
1384-
tcx.sess.delay_span_bug(
1385-
DUMMY_SP,
1386-
&format!(
1387-
"unexpected const parent path def {:?}", x
1388-
),
1389-
);
1390-
return Some(tcx.types.err);
1362+
if let Some(path) = path {
1363+
let arg_index = path.segments.iter()
1364+
.filter_map(|seg| seg.args.as_ref())
1365+
.map(|generic_args| generic_args.args.as_ref())
1366+
.find_map(|args| {
1367+
args.iter()
1368+
.filter(|arg| arg.is_const())
1369+
.enumerate()
1370+
.filter(|(_, arg)| arg.id() == hir_id)
1371+
.map(|(index, _)| index)
1372+
.next()
1373+
})
1374+
.or_else(|| {
1375+
if !fail {
1376+
None
1377+
} else {
1378+
bug!("no arg matching AnonConst in path")
13911379
}
1392-
};
1393-
1394-
generics.params.iter()
1395-
.filter(|param| {
1396-
if let ty::GenericParamDefKind::Const = param.kind {
1397-
true
1398-
} else {
1399-
false
1400-
}
1401-
})
1402-
.nth(arg_index)
1403-
.map(|param| tcx.type_of(param.def_id))
1404-
// This is no generic parameter associated with the arg. This is
1405-
// probably from an extra arg where one is not needed.
1406-
.unwrap_or(tcx.types.err)
1407-
}
1408-
x => {
1409-
if !fail {
1410-
return None;
1380+
})?;
1381+
1382+
// We've encountered an `AnonConst` in some path, so we need to
1383+
// figure out which generic parameter it corresponds to and return
1384+
// the relevant type.
1385+
let generics = match path.res {
1386+
Res::Def(DefKind::Ctor(..), def_id) => {
1387+
tcx.generics_of(tcx.parent(def_id).unwrap())
14111388
}
1412-
tcx.sess.delay_span_bug(
1413-
DUMMY_SP,
1414-
&format!(
1415-
"unexpected const parent path {:?}", x
1416-
),
1417-
);
1418-
tcx.types.err
1389+
Res::Def(_, def_id) => tcx.generics_of(def_id),
1390+
Res::Err => return Some(tcx.types.err),
1391+
_ if !fail => return None,
1392+
res => {
1393+
tcx.sess.delay_span_bug(
1394+
DUMMY_SP,
1395+
&format!(
1396+
"unexpected const parent path def {:?}",
1397+
res,
1398+
),
1399+
);
1400+
return Some(tcx.types.err);
1401+
}
1402+
};
1403+
1404+
generics.params.iter()
1405+
.filter(|param| {
1406+
if let ty::GenericParamDefKind::Const = param.kind {
1407+
true
1408+
} else {
1409+
false
1410+
}
1411+
})
1412+
.nth(arg_index)
1413+
.map(|param| tcx.type_of(param.def_id))
1414+
// This is no generic parameter associated with the arg. This is
1415+
// probably from an extra arg where one is not needed.
1416+
.unwrap_or(tcx.types.err)
1417+
} else {
1418+
if !fail {
1419+
return None;
14191420
}
1421+
tcx.sess.delay_span_bug(
1422+
DUMMY_SP,
1423+
&format!(
1424+
"unexpected const parent path {:?}",
1425+
parent_node,
1426+
),
1427+
);
1428+
return Some(tcx.types.err);
14201429
}
14211430
}
14221431

src/libsyntax/parse/parser.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -5244,9 +5244,13 @@ impl<'a> Parser<'a> {
52445244
// FIXME(const_generics): to distinguish between idents for types and consts,
52455245
// we should introduce a GenericArg::Ident in the AST and distinguish when
52465246
// lowering to the HIR. For now, idents for const args are not permitted.
5247-
return Err(
5248-
self.fatal("identifiers may currently not be used for const generics")
5249-
);
5247+
if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) {
5248+
self.parse_literal_maybe_minus()?
5249+
} else {
5250+
return Err(
5251+
self.fatal("identifiers may currently not be used for const generics")
5252+
);
5253+
}
52505254
} else {
52515255
self.parse_literal_maybe_minus()?
52525256
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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 IsZeroTrait<const IS_ZERO: bool>{}
7+
8+
impl IsZeroTrait<{0u8 == 0u8}> for () {}
9+
10+
impl IsZeroTrait<true> for ((),) {}
11+
12+
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/condition-in-trait-const-arg.rs:3:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+

0 commit comments

Comments
 (0)