Repository: rust
Issue: improve diagnostic for trait impl involving (infinite?) type recursion and constants
Labels: C-enhancement,A-diagnostics,A-trait-system,T-compiler

I'm seeing an internal compiler error in something I *think* is related to infinite recursion in the type system while implementing a generic trait.

I tried compiling this code via cargo as a library crate (all of this in `lib.rs`):
```
use std::ops::Mul;
use std::f64::consts::PI;

pub trait Unit: Default + Copy + Clone + PartialOrd + PartialEq {}

#[derive(Default, Copy, Clone, PartialOrd, PartialEq)]
pub struct Quantity<U: Unit>(
    pub f64,
    pub U,
);

#[derive(Default, Copy, Clone, PartialOrd, PartialEq)]
pub struct Point<T=f64> {
    pub x: T,
    pub y: T,
}

impl<'b, T> Mul<&'b Point<T>> for f64 where f64: Mul<&'b T> {
    type Output = Point<<f64 as Mul<&'b T>>::Output>;
    fn mul(self, rhs: &'b Point<T>) -> Self::Output { Point{ x: self*&rhs.x, y: self*&rhs.y } }
}

mod detail {  // private with public struct, for use in a public type alias only
    use super::Unit;

    #[derive(Default, Copy, Clone, PartialOrd, PartialEq)]
    pub struct AngleUnit;

    impl Unit for AngleUnit {}

} // mod detail

pub type Angle = Quantity<detail::AngleUnit>;

pub const RADIANS: Angle = Quantity(1.0, detail::AngleUnit{});
pub const DEGREES: Angle = Quantity(RADIANS.0*PI/180.0, detail::AngleUnit{});
```

I expected to see some reasonable compiler error; I'm pretty confident the code is bad.  In particular, if you comment out the last two lines (the definition of the constants), you get a friendlier error:
```
error[E0275]: overflow evaluating the requirement `_: std::marker::Sized`
```
(followed by some less-friendly recursive messages that do eventually truncate).

With those two `const` lines as above, I get:
```
error: internal compiler error: librustc/traits/structural_impls.rs:178: impossible case reached

thread 'main' panicked at 'Box<Any>', librustc_errors/lib.rs:578:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: aborting due to previous error


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.29.1 (b801ae664 2018-09-20) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib

note: some of the compiler flags provided by cargo are hidden
```

## Meta

(see above for version)

Since I'm not completely confident in my ability to run just `rustc` with the same options, here's the output of `RUST_BACKTRACE=1 cargo test`, I get:
```
error: internal compiler error: librustc/traits/structural_impls.rs:178: impossible case reached

thread 'main' panicked at 'Box<Any>', librustc_errors/lib.rs:578:9
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: rustc::util::common::panic_hook
   5: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:479
   6: std::panicking::begin_panic
   7: rustc_errors::Handler::bug
   8: rustc::session::opt_span_bug_fmt::{{closure}}
   9: rustc::ty::context::tls::with_opt::{{closure}}
  10: rustc::ty::context::tls::with_context_opt
  11: rustc::ty::context::tls::with_opt
             at   libstd/panicking.rs12:: 211rustc
::  session ::3opt_span_bug_fmt: 
std::panicking  ::13default_hook: 
rustc::           session  at ::libstd/panicking.rsbug_fmt:
227
  14:   rustc ::4traits: ::structural_implsrustc::::<utilimpl:: commonrustc::::panic_hookty
::context::  Lift <5': tcx>std ::forpanicking ::rustcrust_panic_with_hook::
traits::           SelectionError  at <libstd/panicking.rs':a479>
>::lift_to_tcx  
 6:   15std: ::rustcpanicking::::tybegin_panic::
context::TyCtxt  :: lift_to_global7
: rustc_errors  ::16Handler: ::rustcbug::
traits::select  :: SelectionContext8::: candidate_from_obligation
rustc::session  ::17opt_span_bug_fmt: ::rustc{::{traitsclosure::}select}::
SelectionContext::evaluate_stack  
 9  : 18rustc: ::rustcty::::tycontext::::contexttls::::tlswith_opt::::with_context{
{closure  }19}: 
rustc::  dep_graph10::: graph::rustcDepGraph::::tywith_anon_task::
context::tls  ::20with_context_opt: 
rustc::  traits11::: selectrustc::::SelectionContextty::::evaluate_predicate_recursivelycontext
::tls::  with_opt21
: rustc  ::12infer: ::InferCtxtrustc::::probesession
::opt_span_bug_fmt
  22  : 13: <&rustc'::asession ::mutbug_fmt 
I   as14 : core::rustciter::::traitsiterator::::structural_implsIterator::><::implnext 
rustc::ty  ::23context: ::Lift<<alloc'::tcxvec>:: Vecfor< Trustc>:: traitsas:: SelectionErroralloc<::'veca::>SpecExtend><::Tlift_to_tcx,
 I>  >15::: from_iter
rustc::ty  ::24context: ::TyCtxtrustc::::lift_to_globaltraits
::select  ::16SelectionContext: ::rustccandidate_from_obligation_no_cache::
traits::select  ::25SelectionContext: ::rustccandidate_from_obligation::
ty::context  ::17tls: ::rustcwith_context::
traits::select  ::26SelectionContext: ::evaluate_stackrustc
::dep_graph::  graph18::: DepGraph::rustcwith_anon_task::
ty::  context27::: tls::rustcwith_context::
traits::select::  SelectionContext19::: candidate_from_obligation
rustc::  dep_graph28::: graph::rustcDepGraph::::traitswith_anon_task::
select::SelectionContext  ::20evaluate_stack: 
rustc::  traits29::: selectrustc::::SelectionContextty::::evaluate_predicate_recursivelycontext
::tls  ::21with_context: 
rustc::  infer30::: InferCtxtrustc::::probedep_graph
::graph  ::22DepGraph: ::with_anon_task<
&'  a31 : mutrustc ::Itraits ::asselect ::coreSelectionContext::::iterevaluate_predicate_recursively::
iterator::  Iterator32>: ::rustcnext::
infer::  InferCtxt23::: probe<
alloc::  vec33::: Vec<<T&>' aas  mutalloc ::vec::ISpecExtend <asT ,core ::Iiter>::>iterator::::from_iterIterator
>::next
  24:   34rustc: ::traits<::allocselect::::vecSelectionContext::::Veccandidate_from_obligation_no_cache<
T>   25as:  allocrustc::::vecty::::SpecExtendcontext<::Ttls,:: with_contextI
>>  ::26from_iter: 
rustc::  dep_graph35::: graphrustc::::DepGraphtraits::::with_anon_taskselect
::SelectionContext::  candidate_from_obligation_no_cache27
: rustc  ::36traits: ::rustcselect::::tySelectionContext::::contextcandidate_from_obligation::
tls::  with_context28
: rustc  ::37traits: ::selectrustc::::SelectionContextdep_graph::::evaluate_stackgraph
::DepGraph  ::29with_anon_task: 
rustc::  ty38::: context::rustctls::::traitswith_context::
select::SelectionContext  ::30candidate_from_obligation: 
rustc::dep_graph  ::39graph: ::rustcDepGraph::::traitswith_anon_task::
select  ::31SelectionContext: ::evaluate_stackrustc
::traits::  select40::: SelectionContextrustc::::evaluate_predicate_recursivelyty
::context  ::32tls: ::rustcwith_context::
infer::  InferCtxt41::: probe
rustc  ::33dep_graph: ::<graph&::'DepGrapha:: with_anon_taskmut
 I   42as:  corerustc::::itertraits::::iteratorselect::::IteratorSelectionContext>::::evaluate_predicate_recursivelynext

    4334: : rustc::<inferalloc::::InferCtxtvec::::probeVec
<T>   44as:  <alloc&::'veca:: SpecExtendmut< TI,  asI >core>::::iterfrom_iter::
iterator::  Iterator35>: ::rustcnext::
traits::select  ::45SelectionContext: ::candidate_from_obligation_no_cache<
alloc::  vec36::: Vec<rustcT::>ty ::ascontext ::alloctls::::vecwith_context::
SpecExtend<  T37,:  Irustc>::>dep_graph::::from_itergraph
::DepGraph  ::46with_anon_task: 
rustc::traits  ::38select: ::rustcSelectionContext::::traitscandidate_from_obligation_no_cache::
select  ::47SelectionContext: ::rustccandidate_from_obligation::
ty  ::39context: ::tlsrustc::::with_contexttraits
::select::  SelectionContext48::: evaluate_stackrustc
::dep_graph  ::40graph: ::DepGraphrustc::::with_anon_taskty
::context  ::49tls: ::rustcwith_context::
traits::select  ::41SelectionContext: ::rustccandidate_from_obligation::
dep_graph::graph  ::50DepGraph: ::rustcwith_anon_task::
traits::  select42::: SelectionContextrustc::::evaluate_stacktraits
::select  ::51SelectionContext: ::rustcevaluate_predicate_recursively::
ty  ::43context: ::rustctls::::inferwith_context::
InferCtxt::  probe52
: rustc  ::44dep_graph: ::<graph&::'DepGrapha:: with_anon_taskmut
 I   as53 : corerustc::::itertraits::::iteratorselect::::IteratorSelectionContext>::::evaluate_predicate_recursivelynext

    5445: : <allocrustc::::vecinfer::::VecInferCtxt<::Tprobe>
 as   55alloc: ::vec<::&SpecExtend'<aT ,mut  II> >as:: from_itercore
::  iter46::: iterator::rustcIterator::>traits::::nextselect
::SelectionContext  ::56candidate_from_obligation_no_cache: 
<alloc  ::47vec: ::rustcVec::<tyT::>context ::astls ::allocwith_context::
vec::  SpecExtend48<: Trustc,:: dep_graphI::>graph>::::DepGraphfrom_iter::
with_anon_task
    5749: : rustcrustc::::traitstraits::::selectselect::::SelectionContextSelectionContext::::candidate_from_obligation_no_cachecandidate_from_obligation

    5850: : rustc::rustcty::::traitscontext::::selecttls::::SelectionContextwith_context::
evaluate_stack  
59:   rustc51::: dep_graph::rustcgraph::::tyDepGraph::::contextwith_anon_task::
tls  ::60with_context: 
rustc  ::52traits: ::rustcselect::::dep_graphSelectionContext::::graphcandidate_from_obligation::
DepGraph  ::61with_anon_task: 
rustc::traits  ::53select: ::SelectionContextrustc::::evaluate_stacktraits
::select  ::62SelectionContext: ::rustcevaluate_predicate_recursively::
ty::  context54::: tls::rustcwith_context::
infer::  InferCtxt63::: proberustc
::dep_graph  ::55graph: ::DepGraph<::&with_anon_task'
a   mut64 : Irustc ::astraits ::coreselect::::iterSelectionContext::::iteratorevaluate_predicate_recursively::
Iterator>::  next65
: rustc  ::56infer: ::InferCtxt<::allocprobe::
vec::  Vec66<: T>< &as' aalloc ::mutvec ::ISpecExtend <asT ,core ::Iiter>::>iterator::::from_iterIterator
>::  next57
:   rustc67::: traits::<selectalloc::::SelectionContextvec::::candidate_from_obligation_no_cacheVec
<T  >58 : as rustcalloc::::tyvec::::contextSpecExtend::<tlsT::,with_context 
I>>  ::59from_iter: 
rustc::dep_graph  ::68graph: ::rustcDepGraph::::traitswith_anon_task::
select::SelectionContext  ::60candidate_from_obligation_no_cache: 
rustc::  traits69::: select::rustcSelectionContext::::tycandidate_from_obligation::
context::  tls61::: with_contextrustc
::traits  ::70select: ::SelectionContextrustc::::evaluate_stackdep_graph
::graph::  DepGraph62::: with_anon_task
rustc::  ty71::: contextrustc::::tlstraits::::with_contextselect
::SelectionContext  ::63candidate_from_obligation: 
rustc::  dep_graph72::: graphrustc::::DepGraphtraits::::with_anon_taskselect
::SelectionContext  ::64evaluate_stack: 
rustc::traits::  select73::: SelectionContext::rustcevaluate_predicate_recursively::
ty::context::  tls65::: with_context
rustc::infer  ::74InferCtxt: ::rustcprobe::
dep_graph::graph::  DepGraph66::: with_anon_task
<&'  a75 : mut rustcI:: traitsas:: core::iter::selectiterator::::SelectionContextIterator::>evaluate_predicate_recursively::
next
  76:   rustc67::: infer::<InferCtxtalloc::::probevec
::Vec<  T77>:  <as& 'alloca:: vecmut:: SpecExtendI< Tas,  coreI::>iter>::::iteratorfrom_iter::
Iterator>::  next68
: rustc  ::78traits: ::<selectalloc::::SelectionContextvec::::candidate_from_obligation_no_cacheVec
<T>   69as:  allocrustc::::vecty::::SpecExtendcontext<::Ttls,:: with_contextI
>>  ::70from_iter: 
rustc::dep_graph  ::79graph: ::rustcDepGraph::::traitswith_anon_task::
select::  SelectionContext71::: candidate_from_obligation_no_cacherustc
::traits::  select80::: SelectionContextrustc::::candidate_from_obligationty
::context  ::72tls: ::rustcwith_context::
traits::  select81::: SelectionContextrustc::::evaluate_stackdep_graph
::graph  ::73DepGraph: ::rustcwith_anon_task::
ty::context  ::82tls: ::rustcwith_context::
traits::  select74::: SelectionContextrustc::::candidate_from_obligationdep_graph
::graph  ::83DepGraph: ::rustcwith_anon_task::
traits::  select75::: SelectionContext::rustcevaluate_stack::
traits::select  ::SelectionContext84::: evaluate_predicate_recursivelyrustc
::ty  ::76context: ::tlsrustc::::with_contextinfer
::InferCtxt::  probe85
: rustc  ::77dep_graph: ::graph<::&DepGraph'::awith_anon_task 
mut   I86 : as rustccore::::traitsiter::::selectiterator::::SelectionContextIterator::>evaluate_predicate_recursively::
next
  87  : 78: rustc::<inferalloc::::InferCtxtvec::::probeVec
<T>   88as:  <alloc&::'veca:: SpecExtendmut< TI,  asI >core>::::iterfrom_iter::
iterator::  Iterator79>: ::rustcnext::
traits::select  ::89SelectionContext: ::<candidate_from_obligation_no_cachealloc
::vec  ::80Vec: <rustcT::>ty ::ascontext ::alloctls::::vecwith_context::
SpecExtend<T  ,81 : I>rustc>::::dep_graphfrom_iter::
graph::DepGraph  ::90with_anon_task: 
rustc::  traits82::: select::rustcSelectionContext::::traitscandidate_from_obligation_no_cache::
select::SelectionContext  ::91candidate_from_obligation: 
rustc::  ty83::: contextrustc::::tlstraits::::with_contextselect
::SelectionContext::  evaluate_stack92
: rustc  ::84dep_graph: ::graphrustc::::DepGraphty::::with_anon_taskcontext
::tls::  with_context93
: rustc  ::85traits: ::selectrustc::::SelectionContextdep_graph::::candidate_from_obligationgraph
::DepGraph::  with_anon_task94
: rustc  ::86traits: ::selectrustc::::SelectionContexttraits::::evaluate_stackselect
::SelectionContext::  evaluate_predicate_recursively95
: rustc  ::87ty: ::contextrustc::::tlsinfer::::with_contextInferCtxt
::probe  
96:   rustc88::: dep_graph::<graph&::'DepGrapha:: with_anon_taskmut
 I   97as:  rustccore::::traitsiter::::selectiterator::::SelectionContextIterator::>evaluate_predicate_recursively::
next
  98  : 89rustc: ::infer<::allocInferCtxt::::vecprobe::
Vec<T  >99 : as< &alloc'::avec ::mutSpecExtend <IT ,as  Icore>::>iter::::from_iteriterator
::Iterator  90: rustc::>traits::::nextselect
::SelectionContext::candidate_from_obligation_no_cache
query stack during panic:  
91: rustc::ty::context::tls::with_context
  92: rustc::dep_graph::graph::DepGraph::with_anon_task
  93: rustc::traits::select::SelectionContext::candidate_from_obligation
  94: rustc::traits::select::SelectionContext::evaluate_stack
  95: rustc::ty::context::tls::with_context
  96: rustc::dep_graph::graph::DepGraph::with_anon_task
  97: rustc::traits::select::SelectionContext::evaluate_predicate_recursively
  98: rustc::infer::InferCtxt::probe
  99: <&'a mut I as core::iter::iterator::Iterator>::next
query stack during panic:
#0 [evaluate_obligation] evaluating trait selection obligation `f64: std::ops::Mul<_>`
#1 [typeck_tables_of] processing `DEGREES`
end of query stack
#0 [evaluate_obligation] evaluating trait selection obligation `f64: std::ops::Mul<_>`
#1 [typeck_tables_of] processing `DEGREES`
end of query stack
```