diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 1141425c554..3dba00d1fb1 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -38,6 +38,7 @@ use syntax_pos::Span; #[derive(Clone, Debug)] pub enum PatternError { + AssociatedConstInPattern(Span), StaticInPattern(Span), FloatBug, NonConstPath(Span), @@ -150,7 +151,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { BindingMode::ByValue => mutability == Mutability::Mut, BindingMode::ByRef(_, bk) => { write!(f, "ref ")?; - bk == BorrowKind::Mut + match bk { BorrowKind::Mut { .. } => true, _ => false } } }; if is_mut { @@ -462,7 +463,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { (Mutability::Not, BindingMode::ByValue), ty::BindByReference(hir::MutMutable) => (Mutability::Not, BindingMode::ByRef( - region.unwrap(), BorrowKind::Mut)), + region.unwrap(), BorrowKind::Mut { allow_two_phase_borrow: false })), ty::BindByReference(hir::MutImmutable) => (Mutability::Not, BindingMode::ByRef( region.unwrap(), BorrowKind::Shared)), @@ -672,6 +673,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { -> Pattern<'tcx> { let ty = self.tables.node_id_to_type(id); let def = self.tables.qpath_def(qpath, id); + let is_associated_const = match def { + Def::AssociatedConst(_) => true, + _ => false, + }; let kind = match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = self.tables.node_substs(id); @@ -697,7 +702,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } }, None => { - self.errors.push(PatternError::StaticInPattern(span)); + self.errors.push(if is_associated_const { + PatternError::AssociatedConstInPattern(span) + } else { + PatternError::StaticInPattern(span) + }); PatternKind::Wild }, } @@ -814,7 +823,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let field = Field::new(i); let val = match cv.val { ConstVal::Value(miri) => const_val_field( - self.tcx, self.param_env, instance, + self.tcx, self.param_env, instance, span, Some(variant_index), field, miri, cv.ty, ).unwrap(), _ => bug!("{:#?} is not a valid tuple", cv), @@ -842,7 +851,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let field = Field::new(i); let val = match cv.val { ConstVal::Value(miri) => const_val_field( - self.tcx, self.param_env, instance, None, field, miri, cv.ty, + self.tcx, self.param_env, instance, span, + None, field, miri, cv.ty, ).unwrap(), _ => bug!("{:#?} is not a valid tuple", cv), }; @@ -859,7 +869,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let field = Field::new(i); let val = match cv.val { ConstVal::Value(miri) => const_val_field( - self.tcx, self.param_env, instance, None, field, miri, cv.ty, + self.tcx, self.param_env, instance, span, + None, field, miri, cv.ty, ).unwrap(), _ => bug!("{:#?} is not a valid tuple", cv), }; @@ -877,7 +888,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let field = Field::new(i); let val = match cv.val { ConstVal::Value(miri) => const_val_field( - self.tcx, self.param_env, instance, None, field, miri, cv.ty, + self.tcx, self.param_env, instance, span, + None, field, miri, cv.ty, ).unwrap(), _ => bug!("{:#?} is not a valid tuple", cv), }; diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 6c1d762c912..c2f9690b9f1 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -374,6 +374,7 @@ pub fn const_val_field<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, instance: ty::Instance<'tcx>, + span: Span, variant: Option, field: mir::Field, val: Value, @@ -385,7 +386,7 @@ pub fn const_val_field<'a, 'tcx>( ty, })), Err(err) => Err(ConstEvalErr { - span: tcx.def_span(instance.def_id()), + span, kind: err.into(), }), } @@ -455,7 +456,6 @@ pub fn const_eval_provider<'a, 'tcx>( trace!("const eval: {:?}", key); let cid = key.value; let def_id = cid.instance.def.def_id(); - let span = tcx.def_span(def_id); if tcx.is_foreign_item(def_id) { let id = tcx.interpret_interner.get_cached(def_id); @@ -479,6 +479,7 @@ pub fn const_eval_provider<'a, 'tcx>( if let Some(id) = tcx.hir.as_local_node_id(def_id) { let tables = tcx.typeck_tables_of(def_id); + let span = tcx.def_span(def_id); // Do match-check before building MIR if tcx.check_match(def_id).is_err() { @@ -511,6 +512,7 @@ pub fn const_eval_provider<'a, 'tcx>( if tcx.is_static(def_id).is_some() { ecx.report(&mut err, true, None); } + let span = ecx.frame().span; ConstEvalErr { kind: err.into(), span, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 08152019003..71450f42665 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1637,9 +1637,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M }; err.span_label(span, e.to_string()); let mut last_span = None; - for &Frame { instance, span, .. } in self.stack().iter().rev() { + // skip 1 because the last frame is just the environment of the constant + for &Frame { instance, span, .. } in self.stack().iter().skip(1).rev() { // make sure we don't emit frames that are duplicates of the previous if explicit_span == Some(span) { + last_span = Some(span); continue; } if let Some(last) = last_span { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 6aa8b7e5449..8018073883f 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -203,6 +203,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { bx.tcx(), ty::ParamEnv::empty(traits::Reveal::All), self.instance, + constant.span, None, mir::Field::new(field as usize), c,