I received this compiler bug:
sand:mesa_x dpp$ cargo test
Compiling mesa_x v0.1.0 (/Users/dpp/proj/mesa_x)
error: internal compiler error: src/librustc_traits/normalize_erasing_regions.rs:42: could not fully normalize `fn() -> <impl combine::Parser as combine::Parser>::PartialState {<<impl combine::Parser as combine::Parser>::PartialState as std::default::Default>::default}`
thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:931:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
note: the compiler unexpectedly panicked. this is a bug.
Compiling with this cargo.toml file:
[package]
name = "mesa_x"
version = "0.1.0"
authors = ["David Pollak <[email protected]>"]
edition = "2018"
[dependencies]
# nom = "5.0.1"
combine = "3.8.1"
And this main.rs:
#[macro_use]
extern crate combine;
use combine::parser::char::{alpha_num, char, digit, letter, spaces};
use combine::stream::{Stream};
use combine::{
between, choice, attempt, easy,
many, many1, none_of, optional, parser, sep_by, Parser,
};
#[derive(Debug, PartialEq)]
pub struct Address {}
#[derive(Debug, PartialEq)]
pub enum Range {}
#[derive(Debug, PartialEq)]
pub enum Function {}
#[derive(Debug, PartialEq)]
pub enum Expression {
Int(i128),
Float(f64),
Str(String),
Identifier(String),
Address(Address),
Range(Range),
Function(String, Vec<Expression>),
Infix(Function, Box<Expression>, Box<Expression>),
Expression(Box<Expression>),
}
// `impl Parser` can be used to create reusable parsers with zero overhead
fn expr_<I>() -> impl Parser<Input = I, Output = Expression>
where
I: Stream<Item = char, Error = easy::ParseError<I>>,
// Necessary due to rust-lang/rust#24159
// I::Error: ParseError<I::Item, I::Range, I::Position>,
{
let int2 = between(optional(spaces()), optional(spaces()), (optional(char('-')), many1(digit())))
.and_then(|(sign, s): (Option<char>, String)| {
match (sign, s.parse::<i128>()) {
(Some('-'), Ok(r)) => Ok(Expression::Int(r * -1i128)),
(_, Ok(r)) => Ok(Expression::Int(r)),
(_, Err(_x)) => Err(easy::Error::Expected(easy::Info::Borrowed("combine"))),
}
});
let string = between(
(optional(spaces()), char('"')),
(char('"'), optional(spaces())),
many(none_of("\"".chars())),
)
.map(|s| Expression::Str(s));
let identifier = (spaces(), letter(), many(alpha_num()))
.map(|(_, c, st): ((), char, String)| c.to_string() + &st);
let identifier2 = (spaces(), letter(), many(alpha_num()), spaces())
.map(|(_, c, st, _): ((), char, String, ())| Expression::Identifier(c.to_string() + &st));
let comma_list = sep_by(expr(), (optional(spaces()), char(','), optional(spaces()))).map(|v: Vec<Expression>| v);
let function = (
identifier,
between(char('('),
char(')'), comma_list)
)
.map(|(id, exprs)| Expression::Function(id, exprs));
choice((attempt(function), attempt(identifier2), attempt(string), attempt(int2))) //.skip_spaces()
}
parser! {
fn expr[I]()(I) -> Expression
where [I: Stream<Item = char, Error = easy::ParseError<I>>]
{
expr_()
}
}
#[test]
fn test_parsing() {
let test_exprs = vec![
r#"147"#,
r#""Hello World""#,
r#"true"#,
r#"if(32, "yes", "no")"#,
r#"if(true, "yes", "no")"#,
r#" "Hello World""#,
r#"-32"#,
r#"32.99"#,
r#"-32.822"#,
//r#"SuM(a1:$B7)"#,
//r#"3 + 39"#,
//r#"IF(a1, SUM(a1:$b$7), 3 + 39)"#,
];
for item in test_exprs {
match expr().easy_parse(item) {
Ok((_x, "")) => {
//println!("Got {:#?}", x);
assert!(true)},
Ok((_, x)) => assert!(
false,
format!("Failed to parse whole thing... remaining '{}'", x)
),
Err(x) => assert!(false, format!("Trying '{}', got Error {:#?}", item, x)),
}
}
}
fn main() {
println!("Hello, world!");
}
If possible, a self-contained reproducer in the playground would be quite helpful towards fixing the bug.
@Centril -- I tried, but the combine crate is not a default crate on the playground. How can I add a crate to a playground page? Sorry for the n00b question
@dpp You can't. What I would do is inline the pieces you need from combine into your local crate until you can reproduce the issue without combine. Once you've done that, it's a good idea to start minimizing (but once we have a playground link it gets easier to help).
馃檮
Okay... y'all have a bug that causes the compiler to panic. This is suboptimal in a language that is supposed to make guarantees about this kinda thing. But okay... there's a panic in the compiler.
Me... a Rust n00b, but a person who's been doing open source for 29 years and have my share
of non-trivial projects... I get that asking folks to help out and filing bugs in a uniform way.
But you've just asked me to copy/paste 13,000 LoC into the playground and nibble away at the
problem so I have a minimally reproducible example... because it's too difficult for the compiler
team that should pride itself on having zero panics to create a new project and copy/paste
the Cargo.toml and main.rs code from the bug .
Not real welcoming.
@dpp I think there鈥檚 some misunderstanding here:
If possible, a self-contained reproducer in the playground would be quite helpful towards fixing the bug.
as @Centril wrote, he was just trying to guide you to create a mcve. If time is tough for you, just leave this ICE here, mvce of an ICE is not a must from the original reporter, people from the community will pick this up to minimize as the E-needs-mvce label was already added.
And thanks for your reporting :)
triage P-high, at least to learn more about the nature of this bug itself (e.g. getting the MCVE, and/or a stack trace...)
Not minimal but maybe small enough (playground):
use std::marker::PhantomData;
trait StreamError<Item, Range>: Sized {}
trait ParseError<Item, Range>: Sized {
type StreamError: StreamError<Item, Range>;
}
struct FastResult<T, E> {
_marker: PhantomData<(T, E)>,
}
type ConsumedResult<O, I> = FastResult<O, <I as Stream>::Error>;
trait Stream {
type Item;
type Range;
type Error: ParseError<Self::Item, Self::Range>;
}
enum Error<T, R> {
Expected(PhantomData<(T, R)>),
}
impl<Item, Range> StreamError<Item, Range> for Error<Item, Range> {}
impl<Item, Range> ParseError<Item, Range> for Errors<Item, Range> {
type StreamError = Error<Item, Range>;
}
type EasyParseError<S> = Errors<<S as Stream>::Item, <S as Stream>::Range>;
struct Errors<I, R> {
_marker: PhantomData<(I, R)>,
}
fn token<I>(_c: I::Item) -> Token<I>
where
I: Stream,
I::Item: PartialEq,
{
unimplemented!()
}
struct Token<I>
where
I: Stream,
{
_marker: PhantomData<I>,
}
impl<I> Parser for Token<I>
where
I: Stream,
{
type Input = I;
type Output = I::Item;
type PartialState = ();
}
struct AndThen<P, F>(P, F);
impl<P, F, O, E, I> Parser for AndThen<P, F>
where
I: Stream,
P: Parser<Input = I>,
F: FnMut(P::Output) -> Result<O, E>,
E: Into<<I::Error as ParseError<I::Item, I::Range>>::StreamError>,
I::Error: ParseError<I::Item, I::Range>,
{
type Input = P::Input;
type Output = O;
type PartialState = P::PartialState;
}
trait Parser {
type Input: Stream;
type Output;
type PartialState: Default;
fn parse_mode(
&mut self,
_input: &mut Self::Input,
_state: &mut Self::PartialState,
) -> ConsumedResult<Self::Output, Self::Input>
where
Self: Sized,
{
unimplemented!()
}
fn and_then<F, O, E, I>(self, _f: F) -> AndThen<Self, F>
where
Self: Parser<Input = I> + Sized,
F: FnMut(Self::Output) -> Result<O, E>,
I: Stream,
E: Into<<I::Error as ParseError<I::Item, I::Range>>::StreamError>,
{
unimplemented!()
}
}
fn expr<I>() -> impl Parser<Input = I, Output = ()>
where
I: Stream<Item = char, Error = EasyParseError<I>>,
{
let int2 = token('-').and_then(|_| Err(Error::Expected(PhantomData)));
int2
}
struct Expr<I>
where
<I as Stream>::Error: ParseError<<I as Stream>::Item, <I as Stream>::Range>,
I: Stream<Item = char, Error = EasyParseError<I>>,
{
_marker: std::marker::PhantomData<fn(I) -> ()>,
}
impl<I> Expr<I>
where
<I as Stream>::Error: ParseError<<I as Stream>::Item, <I as Stream>::Range>,
I: Stream<Item = char, Error = EasyParseError<I>>,
{
#[allow(dead_code)]
fn parse_mode_impl(&mut self, input: &mut I) -> ConsumedResult<(), I> {
let Expr { .. } = *self;
{
let mut state = Default::default();
expr().parse_mode(input, &mut state)
}
}
}
Backtrace details
error: internal compiler error: src/librustc_traits/normalize_erasing_regions.rs:42: could not fully normalize `fn() -> <impl Parser as Parser>::PartialState {<<impl Parser as Parser>::PartialState as std::default::Default>::default}`
thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:931:9
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:77
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:61
4: core::fmt::write
at src/libcore/fmt/mod.rs:1028
5: std::io::Write::write_fmt
at src/libstd/io/mod.rs:1412
6: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:65
7: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:50
8: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:188
9: std::panicking::default_hook
at src/libstd/panicking.rs:205
10: rustc_driver::report_ice
11: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:468
12: std::panicking::begin_panic
13: rustc_errors::HandlerInner::bug
14: rustc_errors::Handler::bug
15: rustc::util::bug::opt_span_bug_fmt::{{closure}}
16: rustc::ty::context::tls::with_opt::{{closure}}
17: rustc::ty::context::tls::with_context_opt
18: rustc::ty::context::tls::with_opt
19: rustc::util::bug::opt_span_bug_fmt
20: rustc::util::bug::bug_fmt
21: rustc::ty::context::GlobalCtxt::enter_local
22: rustc_traits::normalize_erasing_regions::normalize_ty_after_erasing_regions
23: rustc::ty::query::__query_compute::normalize_ty_after_erasing_regions
24: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors for rustc::ty::query::queries::normalize_ty_after_erasing_regions>::compute
25: rustc::dep_graph::graph::DepGraph::with_task_impl
26: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt>::get_query
27: rustc::traits::query::normalize_erasing_regions::<impl rustc::ty::context::TyCtxt>::normalize_erasing_regions
28: <rustc::ty::layout::LayoutCx<rustc::ty::query::TyCtxtAt> as rustc_target::abi::LayoutOf>::layout_of
29: rustc_mir::interpret::operand::<impl rustc_mir::interpret::eval_context::InterpCx<M>>::eval_const_to_op
30: rustc_mir::transform::const_prop::ConstPropagator::eval_constant
31: <rustc_mir::transform::const_prop::ConstPropagator as rustc::mir::visit::MutVisitor>::visit_terminator
32: <rustc_mir::transform::const_prop::ConstProp as rustc_mir::transform::MirPass>::run_pass
33: rustc_mir::transform::run_passes
34: rustc_mir::transform::run_optimization_passes
35: rustc_mir::transform::optimized_mir
36: rustc::ty::query::__query_compute::optimized_mir
37: rustc::ty::query::<impl rustc::ty::query::config::QueryAccessors for rustc::ty::query::queries::optimized_mir>::compute
38: rustc::dep_graph::graph::DepGraph::with_task_impl
39: rustc::ty::query::plumbing::<impl rustc::ty::context::TyCtxt>::get_query
40: rustc_metadata::encoder::EncodeContext::encode_optimized_mir
41: <rustc_metadata::encoder::EncodeContext as rustc::hir::intravisit::Visitor>::visit_item
42: rustc::hir::Crate::visit_all_item_likes
43: rustc_metadata::encoder::EncodeContext::encode_crate_root
44: rustc::ty::context::tls::with_context::{{closure}}
45: rustc_metadata::encoder::encode_metadata
46: rustc_metadata::cstore_impl::<impl rustc::middle::cstore::CrateStore for rustc_metadata::cstore::CStore>::encode_metadata
47: rustc::ty::context::TyCtxt::encode_metadata
48: rustc_interface::passes::start_codegen::{{closure}}
49: rustc_interface::passes::BoxedGlobalCtxt::access::{{closure}}
50: rustc_interface::passes::create_global_ctxt::{{closure}}
51: rustc_interface::queries::Query<T>::compute
52: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::ongoing_codegen
53: rustc_interface::interface::run_compiler_in_existing_thread_pool
54: std::thread::local::LocalKey<T>::with
55: scoped_tls::ScopedKey<T>::set
56: syntax::with_globals
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc 1.40.0 (73528e339 2019-12-16) running on x86_64-unknown-linux-gnu
note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type lib
note: some of the compiler flags provided by cargo are hidden
query stack during panic:
#0 [normalize_ty_after_erasing_regions] normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [Binder(TraitPredicate(<Errors<char, <I as Stream>::Range> as ParseError<char, <I as Stream>::Range>>)), Binder(TraitPredicate(<Errors<char, <I as Stream>::Range> as std::marker::Sized>)), Binder(TraitPredicate(<I as std::marker::Sized>)), Binder(TraitPredicate(<I as Stream>)), Binder(ProjectionPredicate(ProjectionTy { substs: [I], item_def_id: DefId(0:30 ~ playground[41dd]::Stream[0]::Error[0]) }, Errors<char, <I as Stream>::Range>)), Binder(ProjectionPredicate(ProjectionTy { substs: [I], item_def_id: DefId(0:28 ~ playground[41dd]::Stream[0]::Item[0]) }, char))], reveal: All, def_id: None }, value: fn() -> <impl Parser as Parser>::PartialState {<<impl Parser as Parser>::PartialState as std::default::Default>::default} }`
#1 [optimized_mir] processing `Expr::<I>::parse_mode_impl`
end of query stack
error: aborting due to previous error
Seemingly while computing the optimized MIR: evaluating a constant in the const propagator.
Reduced so far:
use std::marker::PhantomData;
trait ParseError<Item, Range> {
type StreamError;
}
trait Stream {
type Item;
type Range;
type Error: ParseError<Self::Item, Self::Range>;
}
impl<Item, Range> ParseError<Item, Range> for Errors<Item, Range> {
type StreamError = ();
}
type EasyParseError<S> = Errors<<S as Stream>::Item, <S as Stream>::Range>;
struct Errors<I, R> {
_marker: PhantomData<(I, R)>,
}
impl<I> Parser for PhantomData<I> {
type Input = I;
type Output = I;
type PartialState = ();
}
struct AndThen<P, I, O, E>(P, I, O, E);
impl<P, O, E, I> Parser for AndThen<P, I, O, E>
where
I: Stream,
P: Parser,
E: Into<<I::Error as ParseError<I::Item, I::Range>>::StreamError>,
{
type Input = P::Input;
type Output = ();
type PartialState = ();
}
trait Parser {
type Input;
type Output;
type PartialState: Default;
fn parse_mode(self, _: Self::Input, _: Self::PartialState)
where
Self: Sized,
{
loop {}
}
}
struct Expr<I>
where
I: Stream<Error = EasyParseError<I>>,
{
_marker: std::marker::PhantomData<fn(I) -> ()>,
}
impl<I> Expr<I>
where
<I as Stream>::Error: ParseError<<I as Stream>::Item, <I as Stream>::Range>,
I: Stream<Error = EasyParseError<I>>,
{
#[allow(dead_code)]
fn parse_mode_impl(self, input: I) {
fn expr<I>() -> impl Parser<Input = I, Output = ()>
where
I: Stream<Error = EasyParseError<I>>,
{
(loop {}) as AndThen<PhantomData<I>, I, (), ()>
}
expr().parse_mode(input, Default::default())
}
}
Reduced more:
#![allow(dead_code)]
trait ParseError {
type StreamError;
}
impl<T> ParseError for T {
type StreamError = ();
}
trait Stream {
type Item;
type Error: ParseError;
}
trait Parser
where
<Self as Parser>::PartialState: Default,
{
type PartialState;
fn parse_mode(_: &Self, _: Self::PartialState) {
loop {}
}
}
impl Stream for () {
type Item = ();
type Error = ();
}
impl Parser for () {
type PartialState = ();
}
struct AndThen<A, B>(core::marker::PhantomData<(A, B)>);
impl<A, B> Parser for AndThen<A, B>
where
A: Stream,
B: Into<<A::Error as ParseError>::StreamError>,
{
type PartialState = ();
}
fn expr<A>() -> impl Parser
where
A: Stream<Error = <A as Stream>::Item>,
{
AndThen::<A, ()>(core::marker::PhantomData)
}
fn parse_mode_impl<A>()
where
<A as Stream>::Error: ParseError,
A: Stream<Error = <A as Stream>::Item>,
{
Parser::parse_mode(&expr::<A>(), Default::default())
}
Curiously, I can't get the latest MVCE to ICE on the latest nightly for Mac, even though it ICEs just fine on the playground.
I am reliably hitting this ICE with nightly-2020-09-07-x86_64-unknown-freebsd, but not with nightly-2020-08-28-x86_64-unknown-freebsd. Unfortunately, I'm hitting it in a large application that only builds on FreeBSD, so my odds of reducing it to a slim test case are slim. But it looks like the same error as in the playground link above.
Most helpful comment
@dpp I think there鈥檚 some misunderstanding here:
as @Centril wrote, he was just trying to guide you to create a mcve. If time is tough for you, just leave this ICE here, mvce of an ICE is not a must from the original reporter, people from the community will pick this up to minimize as the
E-needs-mvcelabel was already added.And thanks for your reporting :)