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:
commit
026447b9b0
71 changed files with 733 additions and 283 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
),
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 = ¶m.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,
|
||||
);
|
||||
|
|
|
@ -1508,9 +1508,29 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<
|
|||
}
|
||||
|
||||
Node::GenericParam(param) => match ¶m.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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -1,6 +0,0 @@
|
|||
#[link(name="library")]
|
||||
extern "C" {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
fn main() { unsafe { foo(); } }
|
|
@ -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(); }
|
||||
}
|
|
@ -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 } )
|
||||
| ^^^^^^^^^^
|
||||
|
|
|
@ -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`.
|
||||
|
|
20
src/test/ui/const-generics/fn-const-param-call.rs
Normal file
20
src/test/ui/const-generics/fn-const-param-call.rs
Normal 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);
|
||||
}
|
8
src/test/ui/const-generics/fn-const-param-call.stderr
Normal file
8
src/test/ui/const-generics/fn-const-param-call.stderr
Normal 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
|
||||
|
26
src/test/ui/const-generics/fn-const-param-infer.rs
Normal file
26
src/test/ui/const-generics/fn-const-param-infer.rs
Normal 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
|
||||
}
|
45
src/test/ui/const-generics/fn-const-param-infer.stderr
Normal file
45
src/test/ui/const-generics/fn-const-param-infer.stderr
Normal 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`.
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
19
src/test/ui/const-generics/raw-ptr-const-param-deref.rs
Normal file
19
src/test/ui/const-generics/raw-ptr-const-param-deref.rs
Normal 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)
|
||||
}
|
|
@ -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
|
||||
|
9
src/test/ui/const-generics/raw-ptr-const-param.rs
Normal file
9
src/test/ui/const-generics/raw-ptr-const-param.rs
Normal 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 _}>;
|
||||
}
|
20
src/test/ui/const-generics/raw-ptr-const-param.stderr
Normal file
20
src/test/ui/const-generics/raw-ptr-const-param.stderr
Normal 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`.
|
|
@ -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() {}
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
11
src/test/ui/issues/auxiliary/issue-57271-lib.rs
Normal file
11
src/test/ui/issues/auxiliary/issue-57271-lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum BaseType {
|
||||
Byte,
|
||||
Char,
|
||||
Double,
|
||||
Float,
|
||||
Int,
|
||||
Long,
|
||||
Short,
|
||||
Boolean,
|
||||
}
|
24
src/test/ui/issues/issue-57271.rs
Normal file
24
src/test/ui/issues/issue-57271.rs
Normal 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() {}
|
25
src/test/ui/issues/issue-57271.stderr
Normal file
25
src/test/ui/issues/issue-57271.stderr
Normal 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`.
|
22
src/test/ui/issues/issue-57399-self-return-impl-trait.rs
Normal file
22
src/test/ui/issues/issue-57399-self-return-impl-trait.rs
Normal 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() {}
|
|
@ -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
|
||||
|
5
src/test/ui/issues/issue-64792-bad-unicode-ctor.rs
Normal file
5
src/test/ui/issues/issue-64792-bad-unicode-ctor.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
struct X {}
|
||||
|
||||
const Y: X = X("ö"); //~ ERROR expected function, found struct `X`
|
||||
|
||||
fn main() {}
|
15
src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
Normal file
15
src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr
Normal 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`.
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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`.
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue