Auto merge of #65322 - tmandry:rollup-frr651r, r=tmandry

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
This commit is contained in:
bors 2019-10-12 06:25:03 +00:00
commit 026447b9b0
71 changed files with 733 additions and 283 deletions

View file

@ -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> {
}
@ -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.

View file

@ -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.

View file

@ -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),
@ -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
@ -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.

View file

@ -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) {

View file

@ -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)
}
}
}

View file

@ -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("{}{}", 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 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 {
false
}
} 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);
if data == max {
p!(write("std::{}::MAX", ui))
} 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);
false
};
if !printed {
// fallback
p!(write("{:?} : ", ct.val), print(ct.ty))
}
_ => {},
}
}
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)?;
}
}
p!(write("\""));
return Ok(self);
}
}
p!(write("{:?} : ", ct.val), print(ct.ty));
};
Ok(self)
}
}

View file

@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::error::{ExpectedFound, TypeError};
use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar};
use crate::mir::interpret::{ConstValue, get_slice_bytes};
use std::rc::Rc;
use std::iter;
use rustc_target::spec::abi;
@ -561,37 +561,39 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
// implement both `PartialEq` and `Eq`, corresponding to
// `structural_match` types.
// FIXME(const_generics): check for `structural_match` synthetic attribute.
match (eagerly_eval(a), eagerly_eval(b)) {
let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) {
(ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => {
// The caller should handle these cases!
bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
}
(ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => {
Ok(a)
return Ok(a);
}
(ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => {
Ok(a)
return Ok(a);
}
(a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _)
if a.ty == b.ty && a_val == b_val =>
{
Ok(tcx.mk_const(ty::Const {
val: a_val,
ty: a.ty,
}))
(ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => {
if a_val == b_val {
Ok(ConstValue::Scalar(a_val))
} else if let ty::FnPtr(_) = a.ty.kind {
let alloc_map = tcx.alloc_map.lock();
let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id);
let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id);
if a_instance == b_instance {
Ok(ConstValue::Scalar(a_val))
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
}
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
}
}
// FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
// saying that we're not handling it intentionally.
(a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => {
let a_bytes = get_slice_bytes(&tcx, a_val);
let b_bytes = get_slice_bytes(&tcx, b_val);
if a_bytes == b_bytes {
Ok(tcx.mk_const(ty::Const {
val: a_val,
ty: a.ty,
}))
Ok(a_val)
} else {
Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
}
@ -602,16 +604,16 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
// FIXME(const_generics): this is wrong, as it is a projection
(ConstValue::Unevaluated(a_def_id, a_substs),
ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => {
let substs =
relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
Ok(tcx.mk_const(ty::Const {
val: ConstValue::Unevaluated(a_def_id, &substs),
ty: a.ty,
}))
}
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
}
let substs =
relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?;
Ok(ConstValue::Unevaluated(a_def_id, &substs))
}
_ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
};
new_const_val.map(|val| tcx.mk_const(ty::Const {
val,
ty: a.ty,
}))
}
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {

View file

@ -1017,34 +1017,25 @@ impl<'tcx> ty::TyS<'tcx> {
}
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
let (param_env, ty) = query.into_parts();
let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
tcx.infer_ctxt()
.enter(|infcx| traits::type_known_to_meet_bound_modulo_regions(
&infcx,
param_env,
ty,
trait_def_id,
DUMMY_SP,
))
is_item_raw(tcx, query, lang_items::CopyTraitLangItem)
}
fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
let (param_env, ty) = query.into_parts();
let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem, None);
tcx.infer_ctxt()
.enter(|infcx| traits::type_known_to_meet_bound_modulo_regions(
&infcx,
param_env,
ty,
trait_def_id,
DUMMY_SP,
))
is_item_raw(tcx, query, lang_items::SizedTraitLangItem)
}
fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
is_item_raw(tcx, query, lang_items::FreezeTraitLangItem)
}
fn is_item_raw<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
item: lang_items::LangItem,
) -> bool {
let (param_env, ty) = query.into_parts();
let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem, None);
let trait_def_id = tcx.require_lang_item(item, None);
tcx.infer_ctxt()
.enter(|infcx| traits::type_known_to_meet_bound_modulo_regions(
&infcx,

View file

@ -1,5 +1,6 @@
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local,
LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue,
@ -788,7 +789,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
..
},
) if borrow_spans.for_closure() => self.report_escaping_closure_capture(
borrow_spans.args_or_use(),
borrow_spans,
borrow_span,
region_name,
category,
@ -806,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
},
) if borrow_spans.for_generator() => self.report_escaping_closure_capture(
borrow_spans.args_or_use(),
borrow_spans,
borrow_span,
region_name,
category,
@ -1195,7 +1196,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn report_escaping_closure_capture(
&mut self,
args_span: Span,
use_span: UseSpans,
var_span: Span,
fr_name: &RegionName,
category: ConstraintCategory,
@ -1203,7 +1204,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
captured_var: &str,
) -> DiagnosticBuilder<'cx> {
let tcx = self.infcx.tcx;
let args_span = use_span.args_or_use();
let mut err = self.cannot_capture_in_long_lived_closure(
args_span,
captured_var,
@ -1223,12 +1224,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
},
Err(_) => "move |<args>| <body>".to_string()
};
let kind = match use_span.generator_kind() {
Some(generator_kind) => match generator_kind {
GeneratorKind::Async(async_kind) => match async_kind {
AsyncGeneratorKind::Block => "async block",
AsyncGeneratorKind::Closure => "async closure",
_ => bug!("async block/closure expected, but async funtion found."),
},
GeneratorKind::Gen => "generator",
}
None => "closure",
};
err.span_suggestion(
args_span,
&format!("to force the closure to take ownership of {} (and any \
other referenced variables), use the `move` keyword",
captured_var),
&format!(
"to force the {} to take ownership of {} (and any \
other referenced variables), use the `move` keyword",
kind,
captured_var
),
suggestion,
Applicability::MachineApplicable,
);

View file

@ -1,6 +1,7 @@
use rustc::hir;
use rustc::hir::def::Namespace;
use rustc::hir::def_id::DefId;
use rustc::hir::GeneratorKind;
use rustc::mir::{
AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
@ -14,7 +15,7 @@ use syntax_pos::Span;
use syntax::symbol::sym;
use super::borrow_set::BorrowData;
use super::{MirBorrowckCtxt};
use super::MirBorrowckCtxt;
use crate::dataflow::move_paths::{InitLocation, LookupResult};
pub(super) struct IncludingDowncast(pub(super) bool);
@ -604,7 +605,7 @@ pub(super) enum UseSpans {
// The access is caused by capturing a variable for a closure.
ClosureUse {
// This is true if the captured variable was from a generator.
is_generator: bool,
generator_kind: Option<GeneratorKind>,
// The span of the args of the closure, including the `move` keyword if
// it's present.
args_span: Span,
@ -631,6 +632,13 @@ impl UseSpans {
}
}
pub(super) fn generator_kind(self) -> Option<GeneratorKind> {
match self {
UseSpans::ClosureUse { generator_kind, .. } => generator_kind,
_ => None,
}
}
// Add a span label to the arguments of the closure, if it exists.
pub(super) fn args_span_label(
self,
@ -656,7 +664,7 @@ impl UseSpans {
/// Returns `false` if this place is not used in a closure.
pub(super) fn for_closure(&self) -> bool {
match *self {
UseSpans::ClosureUse { is_generator, .. } => !is_generator,
UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(),
_ => false,
}
}
@ -664,7 +672,7 @@ impl UseSpans {
/// Returns `false` if this place is not used in a generator.
pub(super) fn for_generator(&self) -> bool {
match *self {
UseSpans::ClosureUse { is_generator, .. } => is_generator,
UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(),
_ => false,
}
}
@ -672,7 +680,7 @@ impl UseSpans {
/// Describe the span associated with a use of a place.
pub(super) fn describe(&self) -> String {
match *self {
UseSpans::ClosureUse { is_generator, .. } => if is_generator {
UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() {
" in generator".to_string()
} else {
" in closure".to_string()
@ -794,19 +802,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let StatementKind::Assign(
box(_, Rvalue::Aggregate(ref kind, ref places))
) = stmt.kind {
let (def_id, is_generator) = match kind {
box AggregateKind::Closure(def_id, _) => (def_id, false),
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
let def_id = match kind {
box AggregateKind::Closure(def_id, _)
| box AggregateKind::Generator(def_id, _, _) => def_id,
_ => return OtherUse(stmt.source_info.span),
};
debug!(
"move_spans: def_id={:?} is_generator={:?} places={:?}",
def_id, is_generator, places
"move_spans: def_id={:?} places={:?}",
def_id, places
);
if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) {
if let Some((args_span, generator_kind, var_span))
= self.closure_span(*def_id, moved_place, places) {
return ClosureUse {
is_generator,
generator_kind,
args_span,
var_span,
};
@ -857,11 +866,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"borrow_spans: def_id={:?} is_generator={:?} places={:?}",
def_id, is_generator, places
);
if let Some((args_span, var_span)) = self.closure_span(
if let Some((args_span, generator_kind, var_span)) = self.closure_span(
*def_id, Place::from(target).as_ref(), places
) {
return ClosureUse {
is_generator,
generator_kind,
args_span,
var_span,
};
@ -884,7 +893,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
def_id: DefId,
target_place: PlaceRef<'cx, 'tcx>,
places: &Vec<Operand<'tcx>>,
) -> Option<(Span, Span)> {
) -> Option<(Span, Option<GeneratorKind>, Span)> {
debug!(
"closure_span: def_id={:?} target_place={:?} places={:?}",
def_id, target_place, places
@ -893,14 +902,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure(
.., args_span, _
.., body_id, args_span, _
) = expr {
for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
match place {
Operand::Copy(place) |
Operand::Move(place) if target_place == place.as_ref() => {
debug!("closure_span: found captured local {:?}", place);
return Some((*args_span, upvar.span));
let body = self.infcx.tcx.hir().body(*body_id);
let generator_kind = body.generator_kind();
return Some((*args_span, generator_kind, upvar.span));
},
_ => {}
}

View file

@ -1272,7 +1272,14 @@ fn collect_const<'tcx>(
) {
debug!("visiting const {:?}", constant);
match constant.val {
let param_env = ty::ParamEnv::reveal_all();
let substituted_constant = tcx.subst_and_normalize_erasing_regions(
param_substs,
param_env,
&constant,
);
match substituted_constant.val {
ConstValue::Scalar(Scalar::Ptr(ptr)) =>
collect_miri(tcx, ptr.alloc_id, output),
ConstValue::Slice { data: alloc, start: _, end: _ } |
@ -1282,12 +1289,6 @@ fn collect_const<'tcx>(
}
}
ConstValue::Unevaluated(def_id, substs) => {
let param_env = ty::ParamEnv::reveal_all();
let substs = tcx.subst_and_normalize_erasing_regions(
param_substs,
param_env,
&substs,
);
let instance = ty::Instance::resolve(tcx,
param_env,
def_id,
@ -1304,7 +1305,7 @@ fn collect_const<'tcx>(
tcx.def_span(def_id), "collection encountered polymorphic constant",
),
}
}
},
_ => {},
}
}

View file

@ -359,6 +359,35 @@ fn main() {}
```
"##,
E0568: r##"
A super trait has been added to an auto trait.
Erroneous code example:
```compile_fail,E0568
#![feature(optin_builtin_traits)]
auto trait Bound : Copy {} // error!
fn main() {}
```
Since an auto trait is implemented on all existing types, adding a super trait
would filter out a lot of those types. In the current example, almost none of
all the existing types could implement `Bound` because very few of them have the
`Copy` trait.
To fix this issue, just remove the super trait:
```
#![feature(optin_builtin_traits)]
auto trait Bound {} // ok!
fn main() {}
```
"##,
E0571: r##"
A `break` statement with an argument appeared in a non-`loop` loop.
@ -576,7 +605,6 @@ Switch to the Rust 2018 edition to use `async fn`.
;
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target
E0568, // auto traits can not have super traits
E0666, // nested `impl Trait` is illegal
E0667, // `impl Trait` in projections
E0696, // `continue` pointing to a labeled block

View file

@ -796,7 +796,12 @@ impl<'a> Resolver<'a> {
if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
let feature = stability.feature;
if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
stability::report_unstable(self.session, feature, reason, issue, is_soft, span);
let node_id = ast::CRATE_NODE_ID;
let soft_handler =
|lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg);
stability::report_unstable(
self.session, feature, reason, issue, is_soft, span, soft_handler
);
}
}
if let Some(depr) = &stability.rustc_depr {

View file

@ -809,31 +809,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: FooBar`,
// instead we suggest `T: Foo + Bar` in that case.
let mut has_bounds = false;
let mut has_bounds = None;
let mut impl_trait = false;
if let Node::GenericParam(ref param) = hir.get(id) {
match param.kind {
hir::GenericParamKind::Type { synthetic: Some(_), .. } => {
// We've found `fn foo(x: impl Trait)` instead of
// `fn foo<T>(x: T)`. We want to suggest the correct
// `fn foo(x: impl Trait + TraitBound)` instead of
// `fn foo<T: TraitBound>(x: T)`. (#63706)
impl_trait = true;
has_bounds = param.bounds.len() > 1;
}
_ => {
has_bounds = !param.bounds.is_empty();
}
let kind = &param.kind;
if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = kind {
// We've found `fn foo(x: impl Trait)` instead of
// `fn foo<T>(x: T)`. We want to suggest the correct
// `fn foo(x: impl Trait + TraitBound)` instead of
// `fn foo<T: TraitBound>(x: T)`. (See #63706.)
impl_trait = true;
has_bounds = param.bounds.get(1);
} else {
has_bounds = param.bounds.get(0);
}
}
let sp = hir.span(id);
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
let sp = if has_bounds {
sp.to(self.tcx
.sess
.source_map()
.next_point(self.tcx.sess.source_map().next_point(sp)))
// `sp` only covers `T`, change it so that it covers `T:` when appropriate.
let sp = if let Some(first_bound) = has_bounds {
sp.until(first_bound.span())
} else {
sp
};
@ -849,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
param,
if impl_trait { " +" } else { ":" },
self.tcx.def_path_str(t.def_id),
if has_bounds { " +"} else { "" },
if has_bounds.is_some() { " + " } else { "" },
)),
Applicability::MaybeIncorrect,
);

View file

@ -1508,9 +1508,29 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
}
Node::GenericParam(param) => match &param.kind {
hir::GenericParamKind::Type { default: Some(ref ty), .. } |
hir::GenericParamKind::Const { ref ty, .. } => {
icx.to_ty(ty)
hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
hir::GenericParamKind::Const { ty: ref hir_ty, .. } => {
let ty = icx.to_ty(hir_ty);
if !tcx.features().const_compare_raw_pointers {
let err = match ty.peel_refs().kind {
ty::FnPtr(_) => Some("function pointers"),
ty::RawPtr(_) => Some("raw pointers"),
_ => None,
};
if let Some(unsupported_type) = err {
feature_gate::emit_feature_err(
&tcx.sess.parse_sess,
sym::const_compare_raw_pointers,
hir_ty.span,
feature_gate::GateIssue::Language,
&format!(
"using {} as const generic parameters is unstable",
unsupported_type
),
);
};
}
ty
}
x => {
if !fail {

View file

@ -2409,6 +2409,8 @@ where
}
}
/// Inserts all new key-values from the iterator and replaces values with existing
/// keys with new values returned from the iterator.
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
where

View file

@ -1627,7 +1627,7 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer.
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.into_os_string());
@ -1637,7 +1637,7 @@ impl From<PathBuf> for Arc<Path> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&Path> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer.
#[inline]
fn from(s: &Path) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.as_os_str());
@ -1647,7 +1647,7 @@ impl From<&Path> for Arc<Path> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer.
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.into_os_string());
@ -1657,7 +1657,7 @@ impl From<PathBuf> for Rc<Path> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&Path> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.as_os_str());
@ -2219,6 +2219,7 @@ impl Path {
/// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
self._join(path.as_ref())
}

View file

@ -192,7 +192,7 @@ use syntax::util::map_in_place::MapInPlace;
use syntax::ptr::P;
use syntax::symbol::{Symbol, kw, sym};
use syntax::parse::ParseSess;
use syntax_pos::{DUMMY_SP, Span};
use syntax_pos::{Span};
use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
@ -1022,7 +1022,7 @@ impl<'a> MethodDef<'a> {
// [fields of next Self arg], [etc]>
let mut patterns = Vec::new();
for i in 0..self_args.len() {
let struct_path = cx.path(DUMMY_SP, vec![type_ident]);
let struct_path = cx.path(trait_.span, vec![type_ident]);
let (pat, ident_expr) = trait_.create_struct_pattern(cx,
struct_path,
struct_def,

@ -1 +1 @@
Subproject commit 8473db5f2af9dc36aaf6f9b053fcc2e0e6ac8026
Subproject commit 14a3b123074e066d64a99886941473058e52197d

View file

@ -16,7 +16,7 @@ fn main() {
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _3 = const Scalar(AllocId(0).0x0) : fn();
// _3 = const main;
// _2 = move _3 as usize (Misc);
// ...
// _1 = move _2 as *const fn() (Misc);

View file

@ -1,23 +0,0 @@
-include ../tools.mk
# Make sure we don't ICE if the linker prints a non-UTF-8 error message.
# ignore-windows
#
# This does not work in its current form on windows, possibly due to
# gcc bugs or something about valid Windows paths. See issue #29151
# for more information.
# ignore-macos
#
# This also does not work on Apple APFS due to the filesystem requiring
# valid UTF-8 paths.
# The zzz it to allow humans to tab complete or glob this thing.
bad_dir := $(TMPDIR)/zzz$$'\xff'
all:
$(RUSTC) library.rs
mkdir $(bad_dir)
mv $(TMPDIR)/liblibrary.a $(bad_dir)
$(RUSTC) -L $(bad_dir) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined

View file

@ -1,6 +0,0 @@
#[link(name="library")]
extern "C" {
fn foo();
}
fn main() { unsafe { foo(); } }

View file

@ -1,10 +0,0 @@
#![crate_type = "staticlib"]
extern "C" {
fn this_symbol_not_defined();
}
#[no_mangle]
pub extern "C" fn foo() {
unsafe { this_symbol_not_defined(); }
}

View file

@ -12,7 +12,7 @@ note: generator is returned here
|
LL | fn foo() -> Box<impl std::future::Future<Output = u32>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
LL | Box::new(async move { x } )
| ^^^^^^^^^^

View file

@ -18,5 +18,5 @@ LL | auto trait MyTrait { fn foo() {} }
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0380, E0567.
Some errors have detailed explanations: E0380, E0567, E0568.
For more information about an error, try `rustc --explain E0380`.

View file

@ -0,0 +1,20 @@
// run-pass
#![feature(const_generics, const_compare_raw_pointers)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn function() -> u32 {
17
}
struct Wrapper<const F: fn() -> u32>;
impl<const F: fn() -> u32> Wrapper<{F}> {
fn call() -> u32 {
F()
}
}
fn main() {
assert_eq!(Wrapper::<{function}>::call(), 17);
}

View file

@ -0,0 +1,8 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/fn-const-param-call.rs:3:12
|
LL | #![feature(const_generics, const_compare_raw_pointers)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View file

@ -0,0 +1,26 @@
#![feature(const_generics, const_compare_raw_pointers)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
struct Checked<const F: fn(usize) -> bool>;
fn not_one(val: usize) -> bool { val != 1 }
fn not_two(val: usize) -> bool { val != 2 }
fn generic_arg<T>(val: T) -> bool { true }
fn generic<T>(val: usize) -> bool { val != 1 }
fn main() {
let _: Option<Checked<{not_one}>> = None;
let _: Checked<{not_one}> = Checked::<{not_one}>;
let _: Checked<{not_one}> = Checked::<{not_two}>; //~ mismatched types
let _ = Checked::<{generic_arg}>;
let _ = Checked::<{generic_arg::<usize>}>;
let _ = Checked::<{generic_arg::<u32>}>; //~ mismatched types
let _ = Checked::<{generic}>; //~ type annotations needed
let _ = Checked::<{generic::<u16>}>;
let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>; //~ mismatched types
}

View file

@ -0,0 +1,45 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/fn-const-param-infer.rs:1:12
|
LL | #![feature(const_generics, const_compare_raw_pointers)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/fn-const-param-infer.rs:16:33
|
LL | let _: Checked<{not_one}> = Checked::<{not_two}>;
| ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two`
|
= note: expected type `Checked<not_one>`
found type `Checked<not_two>`
error[E0308]: mismatched types
--> $DIR/fn-const-param-infer.rs:20:24
|
LL | let _ = Checked::<{generic_arg::<u32>}>;
| ^^^^^^^^^^^^^^^^^^ expected usize, found u32
|
= note: expected type `fn(usize) -> bool`
found type `fn(u32) -> bool {generic_arg::<u32>}`
error[E0282]: type annotations needed
--> $DIR/fn-const-param-infer.rs:22:24
|
LL | let _ = Checked::<{generic}>;
| ^^^^^^^ cannot infer type for `T`
error[E0308]: mismatched types
--> $DIR/fn-const-param-infer.rs:25:40
|
LL | let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::<u32>`, found `generic::<u16>`
|
= note: expected type `Checked<generic::<u32>>`
found type `Checked<generic::<u16>>`
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0282, E0308.
For more information about an error, try `rustc --explain E0282`.

View file

@ -0,0 +1,16 @@
// run-pass
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
pub trait BitLen: Sized {
const BIT_LEN: usize;
}
impl<const L: usize> BitLen for [u8; L] {
const BIT_LEN: usize = 8 * L;
}
fn main() {
let foo = <[u8; 2]>::BIT_LEN;
}

View file

@ -0,0 +1,16 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/issue-62187-encountered-polymorphic-const.rs:3:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
warning: unused variable: `foo`
--> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9
|
LL | let foo = <[u8; 2]>::BIT_LEN;
| ^^^ help: consider prefixing with an underscore: `_foo`
|
= note: `#[warn(unused_variables)]` on by default

View file

@ -0,0 +1,19 @@
// run-pass
#![feature(const_generics, const_compare_raw_pointers)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
const A: u32 = 3;
struct Const<const P: *const u32>;
impl<const P: *const u32> Const<{P}> {
fn get() -> u32 {
unsafe {
*P
}
}
}
fn main() {
assert_eq!(Const::<{&A as *const _}>::get(), 3)
}

View file

@ -0,0 +1,8 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/raw-ptr-const-param-deref.rs:2:12
|
LL | #![feature(const_generics, const_compare_raw_pointers)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View file

@ -0,0 +1,9 @@
#![feature(const_generics, const_compare_raw_pointers)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
struct Const<const P: *const u32>;
fn main() {
let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types
let _: Const<{10 as *const _}> = Const::<{10 as *const _}>;
}

View file

@ -0,0 +1,20 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/raw-ptr-const-param.rs:1:12
|
LL | #![feature(const_generics, const_compare_raw_pointers)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/raw-ptr-const-param.rs:7:38
|
LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}`
|
= note: expected type `Const<{pointer}>`
found type `Const<{pointer}>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -6,4 +6,10 @@
#[derive(Default)]
struct X;
#[deprecated(note="Do not use this")]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
pub struct Step<I> {
_skip: Option<I>,
}
fn main() {}

View file

@ -1,5 +1,9 @@
// edition:2018
#[bench] //~ ERROR use of unstable library feature 'test'
//~| WARN this was previously accepted
fn bench() {}
use bench as _; //~ ERROR use of unstable library feature 'test'
//~| WARN this was previously accepted
fn main() {}

View file

@ -1,5 +1,5 @@
error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:1:3
--> $DIR/bench.rs:3:3
|
LL | #[bench]
| ^^^^^
@ -8,5 +8,14 @@ LL | #[bench]
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
error: aborting due to previous error
error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:7:5
|
LL | use bench as _;
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
error: aborting due to 2 previous errors

View file

@ -0,0 +1,9 @@
struct ConstFn<const F: fn()>;
//~^ ERROR const generics are unstable
//~^^ ERROR using function pointers as const generic parameters is unstable
struct ConstPtr<const P: *const u32>;
//~^ ERROR const generics are unstable
//~^^ ERROR using raw pointers as const generic parameters is unstable
fn main() {}

View file

@ -0,0 +1,39 @@
error[E0658]: const generics are unstable
--> $DIR/feature-gate-const_generics-ptr.rs:1:22
|
LL | struct ConstFn<const F: fn()>;
| ^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
= help: add `#![feature(const_generics)]` to the crate attributes to enable
error[E0658]: const generics are unstable
--> $DIR/feature-gate-const_generics-ptr.rs:5:23
|
LL | struct ConstPtr<const P: *const u32>;
| ^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
= help: add `#![feature(const_generics)]` to the crate attributes to enable
error[E0658]: using function pointers as const generic parameters is unstable
--> $DIR/feature-gate-const_generics-ptr.rs:1:25
|
LL | struct ConstFn<const F: fn()>;
| ^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53020
= help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
error[E0658]: using raw pointers as const generic parameters is unstable
--> $DIR/feature-gate-const_generics-ptr.rs:5:26
|
LL | struct ConstPtr<const P: *const u32>;
| ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/53020
= help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,11 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum BaseType {
Byte,
Char,
Double,
Float,
Int,
Long,
Short,
Boolean,
}

View file

@ -0,0 +1,24 @@
// aux-build:issue-57271-lib.rs
extern crate issue_57271_lib;
use issue_57271_lib::BaseType;
pub enum ObjectType { //~ ERROR recursive type `ObjectType` has infinite size
Class(ClassTypeSignature),
Array(TypeSignature),
TypeVariable(()),
}
pub struct ClassTypeSignature {
pub package: (),
pub class: (),
pub inner: (),
}
pub enum TypeSignature { //~ ERROR recursive type `TypeSignature` has infinite size
Base(BaseType),
Object(ObjectType),
}
fn main() {}

View file

@ -0,0 +1,25 @@
error[E0072]: recursive type `ObjectType` has infinite size
--> $DIR/issue-57271.rs:7:1
|
LL | pub enum ObjectType {
| ^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
LL | Class(ClassTypeSignature),
LL | Array(TypeSignature),
| ------------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
error[E0072]: recursive type `TypeSignature` has infinite size
--> $DIR/issue-57271.rs:19:1
|
LL | pub enum TypeSignature {
| ^^^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
LL | Base(BaseType),
LL | Object(ObjectType),
| ---------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0072`.

View file

@ -0,0 +1,22 @@
// run-pass
trait T {
type T;
}
impl T for i32 {
type T = u32;
}
struct S<A> {
a: A,
}
impl From<u32> for S<<i32 as T>::T> {
fn from(a: u32) -> Self {
Self { a }
}
}
fn main() {}

View file

@ -0,0 +1,8 @@
warning: field is never used: `a`
--> $DIR/issue-57399-self-return-impl-trait.rs:12:5
|
LL | a: A,
| ^^^^
|
= note: `#[warn(dead_code)]` on by default

View file

@ -0,0 +1,5 @@
struct X {}
const Y: X = X("ö"); //~ ERROR expected function, found struct `X`
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0423]: expected function, found struct `X`
--> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
|
LL | struct X {}
| ----------- `X` defined here
LL |
LL | const Y: X = X("ö");
| ^
| |
| did you mean `X { /* fields */ }`?
| help: a constant with a similar name exists: `Y`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0423`.

View file

@ -0,0 +1,11 @@
trait Foo {
fn foo(&self);
}
trait Bar {}
fn do_stuff<T : Bar>(t : T) {
t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope
}
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0599]: no method named `foo` found for type `T` in the current scope
--> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
|
LL | t.foo()
| ^^^ method not found in `T`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it:
|
LL | fn do_stuff<T: Foo + Bar>(t : T) {
| ^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

View file

@ -17,4 +17,5 @@ LL | let (a, b) = copy(NoClone);
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0277, E0568.
For more information about an error, try `rustc --explain E0277`.

View file

@ -6,3 +6,4 @@ LL | auto trait Magic : Sized where Option<Self> : Magic {}
error: aborting due to previous error
For more information about this error, try `rustc --explain E0568`.

View file

@ -6,3 +6,4 @@ LL | auto trait Magic: Copy {}
error: aborting due to previous error
For more information about this error, try `rustc --explain E0568`.

View file

@ -143,7 +143,7 @@ def issue(
cc @{}, do you think you would have time to do the follow-up work?
If so, that would be great!
cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
cc @{}, the PR reviewer, and nominating for compiler team prioritization.
''').format(
relevant_pr_number, tool, status_description,