Auto merge of #70983 - Centril:rollup-npabk7c, r=Centril

Rollup of 8 pull requests

Successful merges:

 - #70784 (Consider methods on fundamental `impl` when method is not found on numeric type)
 - #70843 (Remove the Ord bound that was plaguing drain_filter)
 - #70913 (Replace "rc"/"arc" lang items with Rc/Arc diagnostic items.)
 - #70932 (De-abuse TyKind::Error in pattern type checking)
 - #70952 (Clean up E0511 explanation)
 - #70964 (rustc_session CLI lint parsing: mark a temporary hack as such)
 - #70969 (Fix JSON file_name documentation for macros.)
 - #70975 (Fix internal doc comment nits.)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-04-10 13:05:05 +00:00
commit dbc3cfdd25
28 changed files with 152 additions and 155 deletions

View File

@ -59,8 +59,11 @@ Diagnostics have the following format:
"spans": [
{
/* The file where the span is located.
For spans located within a macro expansion, this will be the
name of the expanded macro in the format "<MACRONAME macros>".
Note that this path may not exist. For example, if the path
points to the standard library, and the rust src is not
available in the sysroot, then it may point to a non-existent
file. Beware that this may also point to the source of an
external crate.
*/
"file_name": "lib.rs",
/* The byte offset where the span starts (0-based, inclusive). */

View File

@ -1727,28 +1727,22 @@ impl<K, V> Clone for Values<'_, K, V> {
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub struct DrainFilter<'a, K, V, F>
where
K: 'a + Ord, // This Ord bound should be removed before stabilization.
K: 'a,
V: 'a,
F: 'a + FnMut(&K, &mut V) -> bool,
{
pred: F,
inner: DrainFilterInner<'a, K, V>,
}
pub(super) struct DrainFilterInner<'a, K, V>
where
K: 'a + Ord,
V: 'a,
{
pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
length: &'a mut usize,
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, K, V, F> Drop for DrainFilter<'a, K, V, F>
impl<K, V, F> Drop for DrainFilter<'_, K, V, F>
where
K: 'a + Ord,
V: 'a,
F: 'a + FnMut(&K, &mut V) -> bool,
F: FnMut(&K, &mut V) -> bool,
{
fn drop(&mut self) {
self.for_each(drop);
@ -1756,11 +1750,11 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, K, V, F> fmt::Debug for DrainFilter<'a, K, V, F>
impl<K, V, F> fmt::Debug for DrainFilter<'_, K, V, F>
where
K: 'a + fmt::Debug + Ord,
V: 'a + fmt::Debug,
F: 'a + FnMut(&K, &mut V) -> bool,
K: fmt::Debug,
V: fmt::Debug,
F: FnMut(&K, &mut V) -> bool,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.inner.peek()).finish()
@ -1768,11 +1762,9 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, K, V, F> Iterator for DrainFilter<'a, K, V, F>
impl<K, V, F> Iterator for DrainFilter<'_, K, V, F>
where
K: 'a + Ord,
V: 'a,
F: 'a + FnMut(&K, &mut V) -> bool,
F: FnMut(&K, &mut V) -> bool,
{
type Item = (K, V);
@ -1785,11 +1777,7 @@ where
}
}
impl<'a, K, V> DrainFilterInner<'a, K, V>
where
K: 'a + Ord,
V: 'a,
{
impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> {
/// Allow Debug implementations to predict the next element.
pub(super) fn peek(&self) -> Option<(&K, &V)> {
let edge = self.cur_leaf_edge.as_ref()?;
@ -1828,12 +1816,7 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F>
where
K: Ord,
F: FnMut(&K, &mut V) -> bool,
{
}
impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
#[stable(feature = "btree_range", since = "1.17.0")]
impl<'a, K, V> Iterator for Range<'a, K, V> {

View File

@ -1094,7 +1094,7 @@ impl<'a, T> IntoIterator for &'a BTreeSet<T> {
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub struct DrainFilter<'a, T, F>
where
T: 'a + Ord,
T: 'a,
F: 'a + FnMut(&T) -> bool,
{
pred: F,
@ -1102,10 +1102,9 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, T, F> Drop for DrainFilter<'a, T, F>
impl<T, F> Drop for DrainFilter<'_, T, F>
where
T: 'a + Ord,
F: 'a + FnMut(&T) -> bool,
F: FnMut(&T) -> bool,
{
fn drop(&mut self) {
self.for_each(drop);
@ -1113,10 +1112,10 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, T, F> fmt::Debug for DrainFilter<'a, T, F>
impl<T, F> fmt::Debug for DrainFilter<'_, T, F>
where
T: 'a + Ord + fmt::Debug,
F: 'a + FnMut(&T) -> bool,
T: fmt::Debug,
F: FnMut(&T) -> bool,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.inner.peek().map(|(k, _)| k)).finish()
@ -1124,10 +1123,9 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, 'f, T, F> Iterator for DrainFilter<'a, T, F>
impl<'a, T, F> Iterator for DrainFilter<'_, T, F>
where
T: 'a + Ord,
F: 'a + 'f + FnMut(&T) -> bool,
F: 'a + FnMut(&T) -> bool,
{
type Item = T;
@ -1143,12 +1141,7 @@ where
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, T, F> FusedIterator for DrainFilter<'a, T, F>
where
T: 'a + Ord,
F: 'a + FnMut(&T) -> bool,
{
}
impl<T, F> FusedIterator for DrainFilter<'_, T, F> where F: FnMut(&T) -> bool {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Extend<T> for BTreeSet<T> {

View File

@ -279,7 +279,8 @@ struct RcBox<T: ?Sized> {
/// type `T`.
///
/// [get_mut]: #method.get_mut
#[cfg_attr(not(test), lang = "rc")]
#[cfg_attr(all(bootstrap, not(test)), lang = "rc")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
ptr: NonNull<RcBox<T>>,

View File

@ -207,7 +207,8 @@ macro_rules! acquire {
/// counting in general.
///
/// [rc_examples]: ../../std/rc/index.html#examples
#[cfg_attr(not(test), lang = "arc")]
#[cfg_attr(all(bootstrap, not(test)), lang = "arc")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Arc<T: ?Sized> {
ptr: NonNull<ArcInner<T>>,

View File

@ -5,8 +5,8 @@ Erroneous code example:
```compile_fail,E0152
#![feature(lang_items)]
#[lang = "arc"]
struct Foo; // error: duplicate lang item found: `arc`
#[lang = "owned_box"]
struct Foo; // error: duplicate lang item found: `owned_box`
```
Lang items are already implemented in the standard library. Unless you are

View File

@ -1,5 +1,6 @@
Invalid monomorphization of an intrinsic function was used. Erroneous code
example:
Invalid monomorphization of an intrinsic function was used.
Erroneous code example:
```compile_fail,E0511
#![feature(platform_intrinsics)]

View File

@ -6,6 +6,6 @@ Examples of erroneous code:
```compile_fail,E0718
#![feature(lang_items)]
#[lang = "arc"]
#[lang = "owned_box"]
static X: u32 = 42;
```

View File

@ -254,7 +254,4 @@ language_item_table! {
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;
TerminationTraitLangItem, "termination", termination, Target::Trait;
Arc, "arc", arc, Target::Struct;
Rc, "rc", rc, Target::Struct;
}

View File

@ -2209,6 +2209,12 @@ impl<'tcx> TyCtxt<'tcx> {
Some(self.mk_generic_adt(def_id, ty))
}
#[inline]
pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
let def_id = self.get_diagnostic_item(name)?;
Some(self.mk_generic_adt(def_id, ty))
}
#[inline]
pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::MaybeUninitLangItem, None);

View File

@ -1829,14 +1829,9 @@ bitflags! {
const IS_BOX = 1 << 6;
/// Indicates whether the type is `ManuallyDrop`.
const IS_MANUALLY_DROP = 1 << 7;
// FIXME(matthewjasper) replace these with diagnostic items
/// Indicates whether the type is an `Arc`.
const IS_ARC = 1 << 8;
/// Indicates whether the type is an `Rc`.
const IS_RC = 1 << 9;
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
/// (i.e., this flag is never set unless this ADT is an enum).
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 10;
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
}
}
@ -2221,12 +2216,6 @@ impl<'tcx> AdtDef {
if Some(did) == tcx.lang_items().manually_drop() {
flags |= AdtFlags::IS_MANUALLY_DROP;
}
if Some(did) == tcx.lang_items().arc() {
flags |= AdtFlags::IS_ARC;
}
if Some(did) == tcx.lang_items().rc() {
flags |= AdtFlags::IS_RC;
}
AdtDef { did, variants, flags, repr }
}
@ -2305,16 +2294,6 @@ impl<'tcx> AdtDef {
self.flags.contains(AdtFlags::IS_PHANTOM_DATA)
}
/// Returns `true` if this is `Arc<T>`.
pub fn is_arc(&self) -> bool {
self.flags.contains(AdtFlags::IS_ARC)
}
/// Returns `true` if this is `Rc<T>`.
pub fn is_rc(&self) -> bool {
self.flags.contains(AdtFlags::IS_RC)
}
/// Returns `true` if this is Box<T>.
#[inline]
pub fn is_box(&self) -> bool {

View File

@ -1864,24 +1864,6 @@ impl<'tcx> TyS<'tcx> {
self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr()
}
/// Returns `true` if this type is an `Arc<T>`.
#[inline]
pub fn is_arc(&self) -> bool {
match self.kind {
Adt(def, _) => def.is_arc(),
_ => false,
}
}
/// Returns `true` if this type is an `Rc<T>`.
#[inline]
pub fn is_rc(&self) -> bool {
match self.kind {
Adt(def, _) => def.is_rc(),
_ => false,
}
}
#[inline]
pub fn is_box(&self) -> bool {
match self.kind {

View File

@ -11,7 +11,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::{symbol::sym, Span};
use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData;
@ -632,20 +632,20 @@ pub(super) enum BorrowedContentSource<'tcx> {
}
impl BorrowedContentSource<'tcx> {
pub(super) fn describe_for_unnamed_place(&self) -> String {
pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
match *self {
BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(),
BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(),
BorrowedContentSource::OverloadedDeref(ty) => {
if ty.is_rc() {
BorrowedContentSource::OverloadedDeref(ty) => match ty.kind {
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
"an `Rc`".to_string()
} else if ty.is_arc() {
"an `Arc`".to_string()
} else {
format!("dereference of `{}`", ty)
}
}
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
"an `Arc`".to_string()
}
_ => format!("dereference of `{}`", ty),
},
BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
}
}
@ -662,22 +662,22 @@ impl BorrowedContentSource<'tcx> {
}
}
pub(super) fn describe_for_immutable_place(&self) -> String {
pub(super) fn describe_for_immutable_place(&self, tcx: TyCtxt<'_>) -> String {
match *self {
BorrowedContentSource::DerefRawPointer => "a `*const` pointer".to_string(),
BorrowedContentSource::DerefSharedRef => "a `&` reference".to_string(),
BorrowedContentSource::DerefMutableRef => {
bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
}
BorrowedContentSource::OverloadedDeref(ty) => {
if ty.is_rc() {
BorrowedContentSource::OverloadedDeref(ty) => match ty.kind {
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => {
"an `Rc`".to_string()
} else if ty.is_arc() {
"an `Arc`".to_string()
} else {
format!("a dereference of `{}`", ty)
}
}
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
"an `Arc`".to_string()
}
_ => format!("a dereference of `{}`", ty),
},
BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
}
}

View File

@ -377,7 +377,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
span,
&format!("`{}` which is behind a {}", place_desc, source_desc),
),
(_, _) => self.cannot_move_out_of(span, &source.describe_for_unnamed_place()),
(_, _) => self.cannot_move_out_of(
span,
&source.describe_for_unnamed_place(self.infcx.tcx),
),
}
}
};

View File

@ -120,7 +120,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
local: the_place_err.local,
projection: proj_base,
});
let pointer_type = source.describe_for_immutable_place();
let pointer_type = source.describe_for_immutable_place(self.infcx.tcx);
opt_source = Some(source);
if let Some(desc) = access_place_desc {
item_msg = format!("`{}`", desc);

View File

@ -1019,7 +1019,9 @@ pub fn get_cmd_lint_options(
for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
let arg_pos = if let lint::Forbid = level {
// forbid is always specified last, so it can't be overridden
// HACK: forbid is always specified last, so it can't be overridden.
// FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is
// fixed and `forbid` works as expected.
usize::max_value()
} else {
passed_arg_pos

View File

@ -144,6 +144,7 @@ symbols! {
any,
arbitrary_enum_discriminant,
arbitrary_self_types,
Arc,
Arguments,
ArgumentV1,
arm_target_feature,
@ -582,6 +583,7 @@ symbols! {
raw_dylib,
raw_identifiers,
raw_ref_op,
Rc,
Ready,
reason,
recursion_limit,

View File

@ -902,8 +902,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error: MethodError<'tcx>,
) {
let rcvr = &args[0];
let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, rcvr_t, lang_item| {
if let Some(new_rcvr_t) = self.tcx.mk_lang_item(rcvr_t, lang_item) {
let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
if let Some(new_rcvr_t) = new_rcvr_t {
if let Ok(pick) = self.lookup_probe(
span,
segment.ident,
@ -931,10 +931,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Try alternative arbitrary self types that could fulfill this call.
// FIXME: probe for all types that *could* be arbitrary self-types, not
// just this whitelist.
try_alt_rcvr(&mut err, rcvr_t, lang_items::OwnedBoxLangItem);
try_alt_rcvr(&mut err, rcvr_t, lang_items::PinTypeLangItem);
try_alt_rcvr(&mut err, rcvr_t, lang_items::Arc);
try_alt_rcvr(&mut err, rcvr_t, lang_items::Rc);
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, lang_items::OwnedBoxLangItem));
try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, lang_items::PinTypeLangItem));
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
}
err.emit();
}

View File

@ -271,11 +271,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
self.associated_item(info.def_id, item_name, Namespace::ValueNS)
});
if let (true, false, SelfSource::MethodCall(expr), Some(_)) = (
// There are methods that are defined on the primitive types and won't be
// found when exploring `all_traits`, but we also need them to be acurate on
// our suggestions (#47759).
let fund_assoc = |opt_def_id: Option<DefId>| {
opt_def_id
.and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
.is_some()
};
let lang_items = tcx.lang_items();
let found_candidate = candidates.next().is_some()
|| fund_assoc(lang_items.i8_impl())
|| fund_assoc(lang_items.i16_impl())
|| fund_assoc(lang_items.i32_impl())
|| fund_assoc(lang_items.i64_impl())
|| fund_assoc(lang_items.i128_impl())
|| fund_assoc(lang_items.u8_impl())
|| fund_assoc(lang_items.u16_impl())
|| fund_assoc(lang_items.u32_impl())
|| fund_assoc(lang_items.u64_impl())
|| fund_assoc(lang_items.u128_impl())
|| fund_assoc(lang_items.f32_impl())
|| fund_assoc(lang_items.f32_runtime_impl())
|| fund_assoc(lang_items.f64_impl())
|| fund_assoc(lang_items.f64_runtime_impl());
if let (true, false, SelfSource::MethodCall(expr), true) = (
actual.is_numeric(),
actual.has_concrete_skeleton(),
source,
candidates.next(),
found_candidate,
) {
let mut err = struct_span_err!(
tcx.sess,

View File

@ -1161,7 +1161,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
match ty_opt {
None => {
// infer the variable's type
// Infer the variable's type.
let var_ty = self.fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
@ -1173,7 +1173,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
var_ty
}
Some(typ) => {
// take type that the user specified
// Take type that the user specified.
self.fcx.locals.borrow_mut().insert(nid, typ);
typ.revealed_ty
}
@ -1244,7 +1244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
intravisit::walk_pat(self, p);
}
// Don't descend into the bodies of nested closures
// Don't descend into the bodies of nested closures.
fn visit_fn(
&mut self,
_: intravisit::FnKind<'tcx>,
@ -1292,7 +1292,7 @@ fn check_fn<'a, 'tcx>(
debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env);
// Create the function context. This is either derived from scratch or,
// Create the function context. This is either derived from scratch or,
// in the case of closures, based on the outer context.
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);

View File

@ -1353,23 +1353,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
def_bm: BindingMode,
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
let err = self.tcx.types.err;
let expected = self.structurally_resolved_type(span, expected);
let (element_ty, slice_ty, inferred) = match expected.kind {
let (element_ty, opt_slice_ty, inferred) = match expected.kind {
// An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
ty::Array(element_ty, len) => {
let min = before.len() as u64 + after.len() as u64;
let (slice_ty, expected) =
let (opt_slice_ty, expected) =
self.check_array_pat_len(span, element_ty, expected, slice, len, min);
(element_ty, slice_ty, expected)
// `opt_slice_ty.is_none()` => `slice.is_none()`.
// Note, though, that opt_slice_ty could be `Some(error_ty)`.
assert!(opt_slice_ty.is_some() || slice.is_none());
(element_ty, opt_slice_ty, expected)
}
ty::Slice(element_ty) => (element_ty, expected, expected),
ty::Slice(element_ty) => (element_ty, Some(expected), expected),
// The expected type must be an array or slice, but was neither, so error.
_ => {
if !expected.references_error() {
self.error_expected_array_or_slice(span, expected);
}
(err, err, err)
let err = self.tcx.types.err;
(err, Some(err), err)
}
};
@ -1379,7 +1382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// Type check the `slice`, if present, against its expected type.
if let Some(slice) = slice {
self.check_pat(&slice, slice_ty, def_bm, ti);
self.check_pat(&slice, opt_slice_ty.unwrap(), def_bm, ti);
}
// Type check the elements after `slice`, if present.
for elt in after {
@ -1390,9 +1393,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type check the length of an array pattern.
///
/// Returns both the type of the variable length pattern
/// (or `tcx.err` in case there is none),
/// and the potentially inferred array type.
/// Returns both the type of the variable length pattern (or `None`), and the potentially
/// inferred array type. We only return `None` for the slice type if `slice.is_none()`.
fn check_array_pat_len(
&self,
span: Span,
@ -1401,20 +1403,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
slice: Option<&'tcx Pat<'tcx>>,
len: &ty::Const<'tcx>,
min_len: u64,
) -> (Ty<'tcx>, Ty<'tcx>) {
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
// Now we know the length...
if slice.is_none() {
// ...and since there is no variable-length pattern,
// we require an exact match between the number of elements
// in the array pattern and as provided by the matched type.
if min_len != len {
self.error_scrutinee_inconsistent_length(span, min_len, len);
if min_len == len {
return (None, arr_ty);
}
self.error_scrutinee_inconsistent_length(span, min_len, len);
} else if let Some(pat_len) = len.checked_sub(min_len) {
// The variable-length pattern was there,
// so it has an array type with the remaining elements left as its size...
return (self.tcx.mk_array(element_ty, pat_len), arr_ty);
return (Some(self.tcx.mk_array(element_ty, pat_len)), arr_ty);
} else {
// ...however, in this case, there were no remaining elements.
// That is, the slice pattern requires more than the array type offers.
@ -1425,14 +1429,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// which we can use to infer the length of the array.
let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
self.demand_eqtype(span, updated_arr_ty, arr_ty);
return (self.tcx.types.err, updated_arr_ty);
return (None, updated_arr_ty);
} else {
// We have a variable-length pattern and don't know the array length.
// This happens if we have e.g.,
// `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
self.error_scrutinee_unfixed_length(span);
}
(self.tcx.types.err, arr_ty)
// If we get here, we must have emitted an error.
(Some(self.tcx.types.err), arr_ty)
}
fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {

View File

@ -40,7 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let item_def_id = self.tcx.hir().local_def_id(item_id);
// This attribute causes us to dump some writeback information
// in the form of errors, which is uSymbolfor unit tests.
// in the form of errors, which is uSymbol for unit tests.
let rustc_dump_user_substs = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_substs);
let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_substs);

View File

@ -1,6 +1,6 @@
#![feature(lang_items)]
#[lang = "arc"]
#[lang = "owned_box"]
struct Foo; //~ ERROR E0152
fn main() {

View File

@ -1,4 +1,4 @@
error[E0152]: found duplicate lang item `arc`
error[E0152]: found duplicate lang item `owned_box`
--> $DIR/E0152.rs:4:1
|
LL | struct Foo;

View File

@ -1,7 +1,7 @@
#![feature(lang_items)]
// Arc is expected to be a struct, so this will error.
#[lang = "arc"] //~ ERROR language item must be applied to a struct
// Box is expected to be a struct, so this will error.
#[lang = "owned_box"] //~ ERROR language item must be applied to a struct
static X: u32 = 42;
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0718]: `arc` language item must be applied to a struct
error[E0718]: `owned_box` language item must be applied to a struct
--> $DIR/E0718.rs:4:1
|
LL | #[lang = "arc"]
| ^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
LL | #[lang = "owned_box"]
| ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item
error: aborting due to previous error

View File

@ -4,4 +4,6 @@ extern crate issue_29181 as foo;
fn main() {
0.homura(); //~ ERROR no method named `homura` found
// Issue #47759, detect existing method on the fundamental impl:
let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type
}

View File

@ -4,6 +4,18 @@ error[E0599]: no method named `homura` found for type `{integer}` in the current
LL | 0.homura();
| ^^^^^^ method not found in `{integer}`
error: aborting due to previous error
error[E0689]: can't call method `exp` on ambiguous numeric type `{float}`
--> $DIR/issue-29181.rs:8:30
|
LL | let _ = |x: f64| x * 2.0.exp();
| ^^^
|
help: you must specify a concrete type for this numeric value, like `f32`
|
LL | let _ = |x: f64| x * 2.0_f32.exp();
| ^^^^^^^
For more information about this error, try `rustc --explain E0599`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0599, E0689.
For more information about an error, try `rustc --explain E0599`.