Skip to content

Commit

Permalink
Auto merge of #65322 - tmandry:rollup-frr651r, r=tmandry
Browse files Browse the repository at this point in the history
Rollup of 15 pull requests

Successful merges:

 - #64337 (libstd: Fix typos in doc)
 - #64986 (Function pointers as const generic arguments)
 - #65048 (Added doc about behavior of extend on HashMap)
 - #65191 (Add some regression tests)
 - #65200 (Add ?Sized bound to a supertrait listing in E0038 error documentation)
 - #65205 (Add long error explanation for E0568)
 - #65220 (Update LLVM for Emscripten exception handling support)
 - #65263 (Deduplicate is_{freeze,copy,sized}_raw)
 - #65266 (Mark Path::join as must_use)
 - #65276 (Don't cc rust-lang/compiler for toolstate changes)
 - #65277 (Query generator kind for error reporting)
 - #65283 (stability: Do not use `buffer_lint` after lowering to HIR)
 - #65289 (Fix suggested bound addition diagnostic)
 - #65310 (deriving: avoid dummy Span on an artificial `type_ident` path)
 - #65321 (Remove painful test that is not pulling its weight)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Oct 12, 2019
2 parents 4b42e91 + b93203f commit 026447b
Show file tree
Hide file tree
Showing 71 changed files with 731 additions and 281 deletions.
14 changes: 9 additions & 5 deletions src/librustc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ trait Foo {
This is similar to the second sub-error, but subtler. It happens in situations
like the following:
```compile_fail
trait Super<A> {}
```compile_fail,E0038
trait Super<A: ?Sized> {}
trait Trait: Super<Self> {
}
Expand All @@ -270,17 +270,21 @@ struct Foo;
impl Super<Foo> for Foo{}
impl Trait for Foo {}
fn main() {
let x: Box<dyn Trait>;
}
```
Here, the supertrait might have methods as follows:
```
trait Super<A> {
fn get_a(&self) -> A; // note that this is object safe!
trait Super<A: ?Sized> {
fn get_a(&self) -> &A; // note that this is object safe!
}
```
If the trait `Foo` was deriving from something like `Super<String>` or
If the trait `Trait` was deriving from something like `Super<String>` or
`Super<T>` (where `Foo` itself is `Foo<T>`), this is okay, because given a type
`get_a()` will definitely return an object of that type.
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,10 @@ impl Body {
hir_id: self.value.hir_id,
}
}

pub fn generator_kind(&self) -> Option<GeneratorKind> {
self.generator_kind
}
}

/// The type of source expression that caused this generator to be created.
Expand Down
14 changes: 11 additions & 3 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,13 @@ pub fn provide(providers: &mut Providers<'_>) {
}

pub fn report_unstable(
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, is_soft: bool, span: Span
sess: &Session,
feature: Symbol,
reason: Option<Symbol>,
issue: u32,
is_soft: bool,
span: Span,
soft_handler: impl FnOnce(&'static lint::Lint, Span, &str),
) {
let msg = match reason {
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
Expand All @@ -511,7 +517,7 @@ pub fn report_unstable(
let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
if fresh {
if is_soft {
sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg);
soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg)
} else {
emit_feature_err(
&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
Expand Down Expand Up @@ -779,10 +785,12 @@ impl<'tcx> TyCtxt<'tcx> {
/// Additionally, this function will also check if the item is deprecated. If so, and `id` is
/// not `None`, a deprecated lint attached to `id` will be emitted.
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
let soft_handler =
|lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg);
match self.eval_stability(def_id, id, span) {
EvalResult::Allow => {}
EvalResult::Deny { feature, reason, issue, is_soft } =>
report_unstable(self.sess, feature, reason, issue, is_soft, span),
report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler),
EvalResult::Unmarked => {
// The API could be uncallable for other reasons, for example when a private module
// was referenced.
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,14 @@ impl<'tcx> AllocMap<'tcx> {
}
}

/// Panics if the `AllocId` does not refer to a function
pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> {
match self.get(id) {
Some(GlobalAlloc::Function(instance)) => instance,
_ => bug!("expected allocation ID {} to point to a function", id),
}
}

/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
/// call this function twice, even with the same `Allocation` will ICE the compiler.
pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
Expand Down
9 changes: 8 additions & 1 deletion src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2602,7 +2602,14 @@ impl<'tcx> Debug for Constant<'tcx> {
impl<'tcx> Display for Constant<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
write!(fmt, "const ")?;
write!(fmt, "{}", self.literal)
// FIXME make the default pretty printing of raw pointers more detailed. Here we output the
// debug representation of raw pointers, so that the raw pointers in the mir dump output are
// detailed and just not '{pointer}'.
if let ty::RawPtr(_) = self.literal.ty.kind {
write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty)
} else {
write!(fmt, "{}", self.literal)
}
}
}

Expand Down
218 changes: 107 additions & 111 deletions src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,125 +863,121 @@ pub trait PrettyPrinter<'tcx>:
}

let u8 = self.tcx().types.u8;
if let ty::FnDef(did, substs) = ct.ty.kind {
p!(print_value_path(did, substs));
return Ok(self);
}
if let ConstValue::Unevaluated(did, substs) = ct.val {
match self.tcx().def_kind(did) {
| Some(DefKind::Static)
| Some(DefKind::Const)
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
_ => if did.is_local() {
let span = self.tcx().def_span(did);
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
p!(write("{}", snip))

match (ct.val, &ct.ty.kind) {
(_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)),
(ConstValue::Unevaluated(did, substs), _) => {
match self.tcx().def_kind(did) {
| Some(DefKind::Static)
| Some(DefKind::Const)
| Some(DefKind::AssocConst) => p!(print_value_path(did, substs)),
_ => if did.is_local() {
let span = self.tcx().def_span(did);
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
p!(write("{}", snip))
} else {
p!(write("_: "), print(ct.ty))
}
} else {
p!(write("_: "), print(ct.ty))
}
},
}
},
(ConstValue::Infer(..), _) => p!(write("_: "), print(ct.ty)),
(ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) =>
p!(write("{}", if data == 0 { "false" } else { "true" })),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) =>
p!(write("{}f32", Single::from_bits(data))),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) =>
p!(write("{}f64", Double::from_bits(data))),
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => {
let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size();
let max = truncate(u128::max_value(), bit_size);

if data == max {
p!(write("std::{}::MAX", ui))
} else {
p!(write("_: "), print(ct.ty))
},
}
return Ok(self);
}
if let ConstValue::Infer(..) = ct.val {
p!(write("_: "), print(ct.ty));
return Ok(self);
}
if let ConstValue::Param(ParamConst { name, .. }) = ct.val {
p!(write("{}", name));
return Ok(self);
}
if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val {
match ct.ty.kind {
ty::Bool => {
p!(write("{}", if data == 0 { "false" } else { "true" }));
return Ok(self);
},
ty::Float(ast::FloatTy::F32) => {
p!(write("{}f32", Single::from_bits(data)));
return Ok(self);
},
ty::Float(ast::FloatTy::F64) => {
p!(write("{}f64", Double::from_bits(data)));
return Ok(self);
},
ty::Uint(ui) => {
let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(ui)).size();
let max = truncate(u128::max_value(), bit_size);
p!(write("{}{}", data, ui))
};
},
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => {
let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i))
.size().bits() as u128;
let min = 1u128 << (bit_size - 1);
let max = min - 1;

let ty = self.tcx().lift(&ct.ty).unwrap();
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
.unwrap()
.size;
match data {
d if d == min => p!(write("std::{}::MIN", i)),
d if d == max => p!(write("std::{}::MAX", i)),
_ => p!(write("{}{}", sign_extend(data, size) as i128, i))
}
},
(ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) =>
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())),
(ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")),
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => {
let instance = {
let alloc_map = self.tcx().alloc_map.lock();
alloc_map.unwrap_fn(ptr.alloc_id)
};
p!(print_value_path(instance.def_id(), instance.substs));
},
_ => {
let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
let byte_str = match (ct.val, &ref_ty.kind) {
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
Some(self.tcx()
.alloc_map.lock()
.unwrap_memory(ptr.alloc_id)
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
},
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
// The `inspect` here is okay since we checked the bounds, and there are
// no relocations (we have an active slice reference here). We don't use
// this result to affect interpreter execution.
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
},
_ => None,
};

if data == max {
p!(write("std::{}::MAX", ui))
if let Some(byte_str) = byte_str {
p!(write("b\""));
for &c in byte_str {
for e in std::ascii::escape_default(c) {
self.write_char(e as char)?;
}
}
p!(write("\""));
true
} else if let (ConstValue::Slice { data, start, end }, ty::Str) =
(ct.val, &ref_ty.kind)
{
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
let s = ::std::str::from_utf8(slice)
.expect("non utf8 str from miri");
p!(write("{:?}", s));
true
} else {
p!(write("{}{}", data, ui))
};
return Ok(self);
},
ty::Int(i) =>{
let bit_size = Integer::from_attr(&self.tcx(), SignedInt(i))
.size().bits() as u128;
let min = 1u128 << (bit_size - 1);
let max = min - 1;

let ty = self.tcx().lift(&ct.ty).unwrap();
let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty))
.unwrap()
.size;
match data {
d if d == min => p!(write("std::{}::MIN", i)),
d if d == max => p!(write("std::{}::MAX", i)),
_ => p!(write("{}{}", sign_extend(data, size) as i128, i))
}
return Ok(self);
},
ty::Char => {
p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap()));
return Ok(self);
}
_ => {},
}
}
if let ty::Ref(_, ref_ty, _) = ct.ty.kind {
let byte_str = match (ct.val, &ref_ty.kind) {
(ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => {
let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty());
Some(self.tcx()
.alloc_map.lock()
.unwrap_memory(ptr.alloc_id)
.get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap())
},
(ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active slice reference here). We don't use this
// result to affect interpreter execution.
Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
},
(ConstValue::Slice { data, start, end }, ty::Str) => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
let s = ::std::str::from_utf8(slice)
.expect("non utf8 str from miri");
p!(write("{:?}", s));
return Ok(self);
},
_ => None,
};
if let Some(byte_str) = byte_str {
p!(write("b\""));
for &c in byte_str {
for e in std::ascii::escape_default(c) {
self.write_char(e as char)?;
false
}
} else {
false
};
if !printed {
// fallback
p!(write("{:?} : ", ct.val), print(ct.ty))
}
p!(write("\""));
return Ok(self);
}
}
p!(write("{:?} : ", ct.val), print(ct.ty));

};
Ok(self)
}
}
Expand Down
Loading

0 comments on commit 026447b

Please sign in to comment.