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:
commit
dbc3cfdd25
@ -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). */
|
||||
|
@ -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> {
|
||||
|
@ -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> {
|
||||
|
@ -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>>,
|
||||
|
@ -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>>,
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -6,6 +6,6 @@ Examples of erroneous code:
|
||||
```compile_fail,E0718
|
||||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "arc"]
|
||||
#[lang = "owned_box"]
|
||||
static X: u32 = 42;
|
||||
```
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "arc"]
|
||||
#[lang = "owned_box"]
|
||||
struct Foo; //~ ERROR E0152
|
||||
|
||||
fn main() {
|
||||
|
@ -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;
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user