Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #70983

Merged
merged 18 commits into from
Apr 10, 2020
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/doc/rustc/src/json.md
Original file line number Diff line number Diff line change
@@ -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). */
41 changes: 12 additions & 29 deletions src/liballoc/collections/btree/map.rs
Original file line number Diff line number Diff line change
@@ -1727,52 +1727,44 @@ 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);
}
}

#[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()
}
}

#[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> {
25 changes: 9 additions & 16 deletions src/liballoc/collections/btree/set.rs
Original file line number Diff line number Diff line change
@@ -1094,40 +1094,38 @@ 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,
inner: super::map::DrainFilterInner<'a, T, ()>,
}

#[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);
}
}

#[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()
}
}

#[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> {
3 changes: 2 additions & 1 deletion src/liballoc/rc.rs
Original file line number Diff line number Diff line change
@@ -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>>,
3 changes: 2 additions & 1 deletion src/liballoc/sync.rs
Original file line number Diff line number Diff line change
@@ -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>>,
4 changes: 2 additions & 2 deletions src/librustc_error_codes/error_codes/E0152.md
Original file line number Diff line number Diff line change
@@ -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
5 changes: 3 additions & 2 deletions src/librustc_error_codes/error_codes/E0511.md
Original file line number Diff line number Diff line change
@@ -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)]
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes/E0718.md
Original file line number Diff line number Diff line change
@@ -6,6 +6,6 @@ Examples of erroneous code:
```compile_fail,E0718
#![feature(lang_items)]

#[lang = "arc"]
#[lang = "owned_box"]
static X: u32 = 42;
```
3 changes: 0 additions & 3 deletions src/librustc_hir/lang_items.rs
Original file line number Diff line number Diff line change
@@ -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;
}
6 changes: 6 additions & 0 deletions src/librustc_middle/ty/context.rs
Original file line number Diff line number Diff line change
@@ -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);
23 changes: 1 addition & 22 deletions src/librustc_middle/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
18 changes: 0 additions & 18 deletions src/librustc_middle/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -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 {
30 changes: 15 additions & 15 deletions src/librustc_mir/borrow_check/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
"an `Arc`".to_string()
} else {
format!("dereference of `{}`", ty)
}
}
_ => 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() {
}
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => {
"an `Arc`".to_string()
} else {
format!("a dereference of `{}`", ty)
}
}
_ => format!("a dereference of `{}`", ty),
},
BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
}
}
5 changes: 4 additions & 1 deletion src/librustc_mir/borrow_check/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
@@ -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),
),
}
}
};
Original file line number Diff line number Diff line change
@@ -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);
4 changes: 3 additions & 1 deletion src/librustc_session/config.rs
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/librustc_span/symbol.rs
Original file line number Diff line number Diff line change
@@ -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,
12 changes: 6 additions & 6 deletions src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
@@ -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();
}
28 changes: 26 additions & 2 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -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,
8 changes: 4 additions & 4 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -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);
38 changes: 22 additions & 16 deletions src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
@@ -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) {
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/writeback.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0152.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![feature(lang_items)]

#[lang = "arc"]
#[lang = "owned_box"]
struct Foo; //~ ERROR E0152

fn main() {
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0152.stderr
Original file line number Diff line number Diff line change
@@ -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;
4 changes: 2 additions & 2 deletions src/test/ui/error-codes/E0718.rs
Original file line number Diff line number Diff line change
@@ -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() {}
6 changes: 3 additions & 3 deletions src/test/ui/error-codes/E0718.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 2 additions & 0 deletions src/test/ui/issues/issue-29181.rs
Original file line number Diff line number Diff line change
@@ -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
}
16 changes: 14 additions & 2 deletions src/test/ui/issues/issue-29181.stderr
Original file line number Diff line number Diff line change
@@ -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();
| ^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0599`.
Some errors have detailed explanations: E0599, E0689.
For more information about an error, try `rustc --explain E0599`.