diff --git a/Cargo.lock b/Cargo.lock index fd8d461c54524..4d7b62e9c559f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,7 +345,6 @@ dependencies = [ "libgit2-sys", "log", "memchr", - "num_cpus", "opener", "openssl", "os_info", @@ -1503,9 +1502,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.23" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700" +checksum = "6e7d3b96ec1fcaa8431cf04a4f1ef5caafe58d5cf7bcc31f09c1626adddb0ffe" dependencies = [ "bitflags", "libc", @@ -1518,9 +1517,9 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883539cb0ea94bab3f8371a98cd8e937bbe9ee7c044499184aa4c17deb643a50" +checksum = "1ee51709364c341fbb6fe2a385a290fb9196753bdde2fc45447d27cd31b11b13" dependencies = [ "curl", "git2", @@ -1975,9 +1974,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.12.24+1.3.0" +version = "0.13.1+1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c" +checksum = "43e598aa7a4faedf1ea1b4608f582b06f0f40211eec551b7ef36019ae3f62def" dependencies = [ "cc", "libc", diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 381097344ec68..e98f33ea86eef 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -1,3 +1,5 @@ +//! Greatest lower bound. See [`lattice`]. + use super::combine::CombineFields; use super::lattice::{self, LatticeDir}; use super::InferCtxt; diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index c47d476963772..32affd6a14e1c 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -1,23 +1,21 @@ -//! # Lattice Variables +//! # Lattice variables //! -//! This file contains generic code for operating on inference variables -//! that are characterized by an upper- and lower-bound. The logic and -//! reasoning is explained in detail in the large comment in `infer.rs`. +//! Generic code for operating on [lattices] of inference variables +//! that are characterized by an upper- and lower-bound. //! -//! The code in here is defined quite generically so that it can be +//! The code is defined quite generically so that it can be //! applied both to type variables, which represent types being inferred, //! and fn variables, which represent function types being inferred. -//! It may eventually be applied to their types as well, who knows. +//! (It may eventually be applied to their types as well.) //! In some cases, the functions are also generic with respect to the //! operation on the lattice (GLB vs LUB). //! -//! Although all the functions are generic, we generally write the -//! comments in a way that is specific to type variables and the LUB -//! operation. It's just easier that way. +//! ## Note //! -//! In general all of the functions are defined parametrically -//! over a `LatticeValue`, which is a value defined with respect to -//! a lattice. +//! Although all the functions are generic, for simplicity, comments in the source code +//! generally refer to type variables and the LUB operation. +//! +//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order) use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::InferCtxt; @@ -27,6 +25,11 @@ use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::TyVar; use rustc_middle::ty::{self, Ty}; +/// Trait for returning data about a lattice, and for abstracting +/// over the "direction" of the lattice operation (LUB/GLB). +/// +/// GLB moves "down" the lattice (to smaller values); LUB moves +/// "up" the lattice (to bigger values). pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>; @@ -41,6 +44,7 @@ pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>; } +/// Relates two types using a given lattice. pub fn super_lattice_tys<'a, 'tcx: 'a, L>( this: &mut L, a: Ty<'tcx>, diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index 57cbe2c54f7ae..bc85a4ac609a7 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -1,3 +1,5 @@ +//! Least upper bound. See [`lattice`]. + use super::combine::CombineFields; use super::lattice::{self, LatticeDir}; use super::InferCtxt; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8b0e7794f92ac..da54ad06e048b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1886,6 +1886,15 @@ impl<'tcx> Ty<'tcx> { } } + #[inline] + pub fn is_array_slice(self) -> bool { + match self.kind() { + Slice(_) => true, + RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)), + _ => false, + } + } + #[inline] pub fn is_array(self) -> bool { matches!(self.kind(), Array(..)) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2202001555084..01b12eec628ec 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1345,7 +1345,7 @@ impl CheckAttrVisitor<'_> { target: Target, item: Option>, ) -> bool { - let is_function = matches!(target, Target::Fn | Target::Method(..)); + let is_function = matches!(target, Target::Fn); if !is_function { self.tcx .sess diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 6dfbdace8e2a0..59c88b6603c22 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -11,7 +11,7 @@ use std::iter; use super::InferCtxtPrivExt; -crate trait InferCtxtExt<'tcx> { +pub trait InferCtxtExt<'tcx> { /*private*/ fn impl_similar_to( &self, @@ -204,6 +204,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { flags.push((sym::_Self, Some("{integral}".to_owned()))); } + if self_ty.is_array_slice() { + flags.push((sym::_Self, Some("&[]".to_owned()))); + } + if let ty::Array(aty, len) = self_ty.kind() { flags.push((sym::_Self, Some("[]".to_owned()))); flags.push((sym::_Self, Some(format!("[{}]", aty)))); diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 0ae2dfa180b9e..a39fff8ddc0bd 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -19,9 +19,10 @@ use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{source_map, FileName, MultiSpan, Span}; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ - FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, + FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote, }; use std::cmp::Ordering; @@ -483,150 +484,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let mut label_span_not_found = || { - if unsatisfied_predicates.is_empty() { - err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); - let is_string_or_ref_str = match actual.kind() { - ty::Ref(_, ty, _) => { - ty.is_str() - || matches!( - ty.kind(), - ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did) - ) - } - ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did), - _ => false, - }; - if is_string_or_ref_str && item_name.name == sym::iter { - err.span_suggestion_verbose( - item_name.span, - "because of the in-memory representation of `&str`, to obtain \ - an `Iterator` over each of its codepoint use method `chars`", - String::from("chars"), - Applicability::MachineApplicable, - ); - } - if let ty::Adt(adt, _) = rcvr_ty.kind() { - let mut inherent_impls_candidate = self - .tcx - .inherent_impls(adt.did) - .iter() - .copied() - .filter(|def_id| { - if let Some(assoc) = self.associated_value(*def_id, item_name) { - // Check for both mode is the same so we avoid suggesting - // incorrect associated item. - match (mode, assoc.fn_has_self_parameter, source) { - (Mode::MethodCall, true, SelfSource::MethodCall(_)) => { - // We check that the suggest type is actually - // different from the received one - // So we avoid suggestion method with Box - // for instance - self.tcx.at(span).type_of(*def_id) != actual - && self.tcx.at(span).type_of(*def_id) != rcvr_ty - } - (Mode::Path, false, _) => true, - _ => false, - } - } else { - false - } - }) - .collect::>(); - if !inherent_impls_candidate.is_empty() { - inherent_impls_candidate.sort(); - inherent_impls_candidate.dedup(); - - // number of type to shows at most. - let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 }; - let type_candidates = inherent_impls_candidate - .iter() - .take(limit) - .map(|impl_item| { - format!("- `{}`", self.tcx.at(span).type_of(*impl_item)) - }) - .collect::>() - .join("\n"); - let additional_types = if inherent_impls_candidate.len() > limit { - format!( - "\nand {} more types", - inherent_impls_candidate.len() - limit - ) - } else { - "".to_string() - }; - err.note(&format!( - "the {item_kind} was found for\n{}{}", - type_candidates, additional_types - )); - } - } - } else { - err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds")); - } - }; - - // If the method name is the name of a field with a function or closure type, - // give a helping note that it has to be called as `(x.f)(...)`. - if let SelfSource::MethodCall(expr) = source { - let field_receiver = - self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() { - ty::Adt(def, substs) if !def.is_enum() => { - let variant = &def.non_enum_variant(); - self.tcx.find_field_index(item_name, variant).map(|index| { - let field = &variant.fields[index]; - let field_ty = field.ty(tcx, substs); - (field, field_ty) - }) - } - _ => None, - }); - - if let Some((field, field_ty)) = field_receiver { - let scope = self.tcx.parent_module(self.body_id).to_def_id(); - let is_accessible = field.vis.is_accessible_from(scope, self.tcx); - - if is_accessible { - if self.is_fn_ty(field_ty, span) { - let expr_span = expr.span.to(item_name.span); - err.multipart_suggestion( - &format!( - "to call the function stored in `{}`, \ - surround the field access with parentheses", - item_name, - ), - vec![ - (expr_span.shrink_to_lo(), '('.to_string()), - (expr_span.shrink_to_hi(), ')'.to_string()), - ], - Applicability::MachineApplicable, - ); - } else { - let call_expr = self - .tcx - .hir() - .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); - - if let Some(span) = call_expr.span.trim_start(item_name.span) { - err.span_suggestion( - span, - "remove the arguments", - String::new(), - Applicability::MaybeIncorrect, - ); - } - } - } - - let field_kind = if is_accessible { "field" } else { "private field" }; - err.span_label(item_name.span, format!("{}, not a method", field_kind)); - } else if lev_candidate.is_none() && static_sources.is_empty() { - label_span_not_found(); - } - } else { - label_span_not_found(); - } - if self.is_fn_ty(rcvr_ty, span) { fn report_function(err: &mut Diagnostic, name: T) { err.note( @@ -645,12 +502,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + let mut custom_span_label = false; + if !static_sources.is_empty() { err.note( "found the following associated functions; to be used as methods, \ functions must have a `self` parameter", ); err.span_label(span, "this is an associated function, not a method"); + custom_span_label = true; } if static_sources.len() == 1 { let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) = @@ -711,6 +571,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut type_params = FxHashMap::default(); let mut bound_spans = vec![]; + // Pick out the list of unimplemented traits on the receiver. + // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute. + let mut unimplemented_traits = FxHashMap::default(); + for (predicate, _parent_pred, cause) in &unsatisfied_predicates { + if let (ty::PredicateKind::Trait(p), Some(cause)) = + (predicate.kind().skip_binder(), cause.as_ref()) + { + if p.trait_ref.self_ty() != rcvr_ty { + // This is necessary, not just to keep the errors clean, but also + // because our derived obligations can wind up with a trait ref that + // requires a different param_env to be correctly compared. + continue; + } + unimplemented_traits.entry(p.trait_ref.def_id).or_insert(( + predicate.kind().rebind(p.trait_ref), + Obligation { + cause: cause.clone(), + param_env: self.param_env, + predicate: predicate.clone(), + recursion_depth: 0, + }, + )); + } + } + let mut collect_type_param_suggestions = |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| { // We don't care about regions here, so it's fine to skip the binder here. @@ -950,6 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } + if !bound_list.is_empty() || !skip_list.is_empty() { let bound_list = bound_list .into_iter() @@ -957,9 +843,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect::>() .join("\n"); let actual_prefix = actual.prefix_string(self.tcx); - err.set_primary_message(&format!( + info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); + let (primary_message, label) = if unimplemented_traits.len() == 1 { + unimplemented_traits + .into_iter() + .next() + .map(|(_, (trait_ref, obligation))| { + if trait_ref.self_ty().references_error() + || actual.references_error() + { + // Avoid crashing. + return (None, None); + } + let OnUnimplementedNote { message, label, .. } = + self.infcx.on_unimplemented_note(trait_ref, &obligation); + (message, label) + }) + .unwrap_or((None, None)) + } else { + (None, None) + }; + let primary_message = primary_message.unwrap_or_else(|| format!( "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" )); + err.set_primary_message(&primary_message); + if let Some(label) = label { + custom_span_label = true; + err.span_label(span, label); + } if !bound_list.is_empty() { err.note(&format!( "the following trait bounds were not satisfied:\n{bound_list}" @@ -971,6 +882,150 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + let mut label_span_not_found = || { + if unsatisfied_predicates.is_empty() { + err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); + let is_string_or_ref_str = match actual.kind() { + ty::Ref(_, ty, _) => { + ty.is_str() + || matches!( + ty.kind(), + ty::Adt(adt, _) if self.tcx.is_diagnostic_item(sym::String, adt.did) + ) + } + ty::Adt(adt, _) => self.tcx.is_diagnostic_item(sym::String, adt.did), + _ => false, + }; + if is_string_or_ref_str && item_name.name == sym::iter { + err.span_suggestion_verbose( + item_name.span, + "because of the in-memory representation of `&str`, to obtain \ + an `Iterator` over each of its codepoint use method `chars`", + String::from("chars"), + Applicability::MachineApplicable, + ); + } + if let ty::Adt(adt, _) = rcvr_ty.kind() { + let mut inherent_impls_candidate = self + .tcx + .inherent_impls(adt.did) + .iter() + .copied() + .filter(|def_id| { + if let Some(assoc) = self.associated_value(*def_id, item_name) { + // Check for both mode is the same so we avoid suggesting + // incorrect associated item. + match (mode, assoc.fn_has_self_parameter, source) { + (Mode::MethodCall, true, SelfSource::MethodCall(_)) => { + // We check that the suggest type is actually + // different from the received one + // So we avoid suggestion method with Box + // for instance + self.tcx.at(span).type_of(*def_id) != actual + && self.tcx.at(span).type_of(*def_id) != rcvr_ty + } + (Mode::Path, false, _) => true, + _ => false, + } + } else { + false + } + }) + .collect::>(); + if !inherent_impls_candidate.is_empty() { + inherent_impls_candidate.sort(); + inherent_impls_candidate.dedup(); + + // number of type to shows at most. + let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 }; + let type_candidates = inherent_impls_candidate + .iter() + .take(limit) + .map(|impl_item| { + format!("- `{}`", self.tcx.at(span).type_of(*impl_item)) + }) + .collect::>() + .join("\n"); + let additional_types = if inherent_impls_candidate.len() > limit { + format!( + "\nand {} more types", + inherent_impls_candidate.len() - limit + ) + } else { + "".to_string() + }; + err.note(&format!( + "the {item_kind} was found for\n{}{}", + type_candidates, additional_types + )); + } + } + } else { + err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds")); + } + }; + + // If the method name is the name of a field with a function or closure type, + // give a helping note that it has to be called as `(x.f)(...)`. + if let SelfSource::MethodCall(expr) = source { + let field_receiver = + self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() { + ty::Adt(def, substs) if !def.is_enum() => { + let variant = &def.non_enum_variant(); + self.tcx.find_field_index(item_name, variant).map(|index| { + let field = &variant.fields[index]; + let field_ty = field.ty(tcx, substs); + (field, field_ty) + }) + } + _ => None, + }); + + if let Some((field, field_ty)) = field_receiver { + let scope = self.tcx.parent_module(self.body_id).to_def_id(); + let is_accessible = field.vis.is_accessible_from(scope, self.tcx); + + if is_accessible { + if self.is_fn_ty(field_ty, span) { + let expr_span = expr.span.to(item_name.span); + err.multipart_suggestion( + &format!( + "to call the function stored in `{}`, \ + surround the field access with parentheses", + item_name, + ), + vec![ + (expr_span.shrink_to_lo(), '('.to_string()), + (expr_span.shrink_to_hi(), ')'.to_string()), + ], + Applicability::MachineApplicable, + ); + } else { + let call_expr = self + .tcx + .hir() + .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); + + if let Some(span) = call_expr.span.trim_start(item_name.span) { + err.span_suggestion( + span, + "remove the arguments", + String::new(), + Applicability::MaybeIncorrect, + ); + } + } + } + + let field_kind = if is_accessible { "field" } else { "private field" }; + err.span_label(item_name.span, format!("{}, not a method", field_kind)); + } else if lev_candidate.is_none() && !custom_span_label { + label_span_not_found(); + } + } else if !custom_span_label { + label_span_not_found(); + } + if actual.is_numeric() && actual.is_fresh() || restrict_type_params { } else { self.suggest_traits_to_import( diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 5cef007a46f0d..66608d09082d7 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use core::mem; use super::super::borrow::DormantMutRef; -use super::super::node::{marker, Handle, InsertResult::*, NodeRef}; +use super::super::node::{marker, Handle, NodeRef}; use super::BTreeMap; use Entry::*; @@ -313,13 +313,13 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(self, value: V) -> &'a mut V { let out_ptr = match self.handle.insert_recursing(self.key, value) { - (Fit(_), val_ptr) => { + (None, val_ptr) => { // SAFETY: We have consumed self.handle and the handle returned. let map = unsafe { self.dormant_map.awaken() }; map.length += 1; val_ptr } - (Split(ins), val_ptr) => { + (Some(ins), val_ptr) => { drop(ins.left); // SAFETY: We have consumed self.handle and the reference returned. let map = unsafe { self.dormant_map.awaken() }; diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index dfce98f97bd44..44f5bc850b852 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -861,11 +861,10 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark /// this edge. This method splits the node if there isn't enough room. /// /// The returned pointer points to the inserted value. - fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *mut V) { + fn insert(mut self, key: K, val: V) -> (Option>, *mut V) { if self.node.len() < CAPACITY { let val_ptr = self.insert_fit(key, val); - let kv = unsafe { Handle::new_kv(self.node, self.idx) }; - (InsertResult::Fit(kv), val_ptr) + (None, val_ptr) } else { let (middle_kv_idx, insertion) = splitpoint(self.idx); let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; @@ -879,7 +878,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark }, }; let val_ptr = insertion_edge.insert_fit(key, val); - (InsertResult::Split(result), val_ptr) + (Some(result), val_ptr) } } } @@ -923,13 +922,12 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, key: K, val: V, edge: Root, - ) -> InsertResult<'a, K, V, marker::Internal> { + ) -> Option> { assert!(edge.height == self.node.height - 1); if self.node.len() < CAPACITY { self.insert_fit(key, val, edge); - let kv = unsafe { Handle::new_kv(self.node, self.idx) }; - InsertResult::Fit(kv) + None } else { let (middle_kv_idx, insertion) = splitpoint(self.idx); let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; @@ -943,7 +941,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, }, }; insertion_edge.insert_fit(key, val, edge); - InsertResult::Split(result) + Some(result) } } } @@ -953,32 +951,26 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark /// this edge. This method splits the node if there isn't enough room, and tries to /// insert the split off portion into the parent node recursively, until the root is reached. /// - /// If the returned result is a `Fit`, its handle's node can be this edge's node or an ancestor. - /// If the returned result is a `Split`, the `left` field will be the root node. - /// The returned pointer points to the inserted value. + /// If the returned result is some `SplitResult`, the `left` field will be the root node. + /// The returned pointer points to the inserted value, which in the case of `SplitResult` + /// is in the `left` or `right` tree. pub fn insert_recursing( self, key: K, value: V, - ) -> (InsertResult<'a, K, V, marker::LeafOrInternal>, *mut V) { + ) -> (Option>, *mut V) { let (mut split, val_ptr) = match self.insert(key, value) { - (InsertResult::Fit(handle), ptr) => { - return (InsertResult::Fit(handle.forget_node_type()), ptr); - } - (InsertResult::Split(split), val_ptr) => (split.forget_node_type(), val_ptr), + (None, val_ptr) => return (None, val_ptr), + (Some(split), val_ptr) => (split.forget_node_type(), val_ptr), }; loop { split = match split.left.ascend() { Ok(parent) => match parent.insert(split.kv.0, split.kv.1, split.right) { - InsertResult::Fit(handle) => { - return (InsertResult::Fit(handle.forget_node_type()), val_ptr); - } - InsertResult::Split(split) => split.forget_node_type(), + None => return (None, val_ptr), + Some(split) => split.forget_node_type(), }, - Err(root) => { - return (InsertResult::Split(SplitResult { left: root, ..split }), val_ptr); - } + Err(root) => return (Some(SplitResult { left: root, ..split }), val_ptr), }; } } @@ -1529,14 +1521,6 @@ impl Handle, marker::K } } -impl Handle, marker::KV> { - pub fn forget_node_type( - self, - ) -> Handle, marker::KV> { - unsafe { Handle::new_kv(self.node.forget_type(), self.idx) } - } -} - impl Handle, Type> { /// Checks whether the underlying node is an `Internal` node or a `Leaf` node. pub fn force( @@ -1621,7 +1605,7 @@ pub enum ForceResult { pub struct SplitResult<'a, K, V, NodeType> { // Altered node in existing tree with elements and edges that belong to the left of `kv`. pub left: NodeRef, K, V, NodeType>, - // Some key and value split off, to be inserted elsewhere. + // Some key and value that existed before and were split off, to be inserted elsewhere. pub kv: (K, V), // Owned, unattached, new node with elements and edges that belong to the right of `kv`. pub right: NodeRef, @@ -1639,11 +1623,6 @@ impl<'a, K, V> SplitResult<'a, K, V, marker::Internal> { } } -pub enum InsertResult<'a, K, V, NodeType> { - Fit(Handle, K, V, NodeType>, marker::KV>), - Split(SplitResult<'a, K, V, NodeType>), -} - pub mod marker { use core::marker::PhantomData; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f5c0a3b5cd849..212ba3bb977d1 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -34,6 +34,11 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \ to have a bounded `RangeInclusive`: `0..=end`" ), + on( + _Self = "[]", + label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" + ), + on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"), on( _Self = "&str", label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index dc288176346bc..6097e62876847 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -224,8 +224,14 @@ where } as usize; if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER { n *= 2; - } else if k >= n { + } else if k > n { n = k; + } else if k == n { + // It is impossible to reach this point. + // On success, k is the returned string length excluding the null. + // On failure, k is the required buffer length including the null. + // Therefore k never equals n. + unreachable!(); } else { return Ok(f2(&buf[..k])); } diff --git a/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs b/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs index 3d8478f06db0e..6eabd9b1015b7 100644 --- a/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs +++ b/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs @@ -29,6 +29,11 @@ extern { #[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have fn foo8() {} +impl S { + #[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function + fn foo9() {} +} + #[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute fn bar1() {} diff --git a/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr b/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr index 1f55a8e72d2cb..bfe7bb2e10dcc 100644 --- a/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr +++ b/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr @@ -7,13 +7,13 @@ LL | #[rustc_legacy_const_generics(0usize)] = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) error: malformed `rustc_legacy_const_generics` attribute input - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:32:1 + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:37:1 | LL | #[rustc_legacy_const_generics] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` error: malformed `rustc_legacy_const_generics` attribute input - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:35:1 + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:40:1 | LL | #[rustc_legacy_const_generics = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` @@ -66,6 +66,14 @@ LL | #[rustc_legacy_const_generics(0)] LL | fn foo8() {} | - non-const generic parameter +error: attribute should be applied to a function + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:5 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo9() {} + | ---------------------------- not a function + error: attribute should be applied to a function --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5 | @@ -82,6 +90,6 @@ LL | fn foo7(); | = help: replace the const parameters with concrete consts -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0044`. diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index b0524f056ef7f..a336d1b0ed55d 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -1,8 +1,8 @@ -error[E0599]: the method `to_string` exists for raw pointer `*const u8`, but its trait bounds were not satisfied +error[E0599]: `*const u8` doesn't implement `std::fmt::Display` --> $DIR/issue-21596.rs:4:22 | LL | println!("{}", z.to_string()); - | ^^^^^^^^^ method cannot be called on `*const u8` due to unsatisfied trait bounds + | ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter | = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 982b6118ce659..e0f75f5c8025f 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -18,16 +18,16 @@ error[E0599]: the method `collect` exists for struct `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>` due to unsatisfied trait bounds | - ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL - | -LL | pub struct Cloned { - | -------------------- doesn't satisfy `_: Iterator` - | ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL | LL | pub struct TakeWhile { | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_` | + ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL + | +LL | pub struct Cloned { + | -------------------- doesn't satisfy `_: Iterator` + | = note: the following trait bounds were not satisfied: `, [closure@$DIR/issue-31173.rs:6:39: 9:6]> as Iterator>::Item = &_` which is required by `Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6]>>: Iterator` diff --git a/src/test/ui/methods/issues/issue-94581.rs b/src/test/ui/methods/issues/issue-94581.rs new file mode 100644 index 0000000000000..df393e91db084 --- /dev/null +++ b/src/test/ui/methods/issues/issue-94581.rs @@ -0,0 +1,7 @@ +fn get_slice() -> &'static [i32] { + &[1, 2, 3, 4] +} + +fn main() { + let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599] +} diff --git a/src/test/ui/methods/issues/issue-94581.stderr b/src/test/ui/methods/issues/issue-94581.stderr new file mode 100644 index 0000000000000..d6be29cf582c3 --- /dev/null +++ b/src/test/ui/methods/issues/issue-94581.stderr @@ -0,0 +1,15 @@ +error[E0599]: `&'static [i32]` is not an iterator + --> $DIR/issue-94581.rs:6:29 + | +LL | let sqsum = get_slice().map(|i| i * i).sum(); + | ^^^ `&'static [i32]` is not an iterator; try calling `.iter()` + | + = note: the following trait bounds were not satisfied: + `&'static [i32]: Iterator` + which is required by `&mut &'static [i32]: Iterator` + `[i32]: Iterator` + which is required by `&mut [i32]: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs index 86d00ca376026..d53ef445afc1b 100644 --- a/src/test/ui/methods/method-call-err-msg.rs +++ b/src/test/ui/methods/method-call-err-msg.rs @@ -16,7 +16,7 @@ fn main() { let y = Foo; y.zero() - .take() //~ ERROR the method + .take() //~ ERROR not an iterator .one(0); y.three::(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied } diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index c1183e053eb43..c410e076dde26 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -40,7 +40,7 @@ note: associated function defined here LL | fn two(self, _: isize, _: isize) -> Foo { self } | ^^^ ---- -------- -------- -error[E0599]: the method `take` exists for struct `Foo`, but its trait bounds were not satisfied +error[E0599]: `Foo` is not an iterator --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; @@ -50,7 +50,7 @@ LL | pub struct Foo; | doesn't satisfy `Foo: Iterator` ... LL | .take() - | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds + | ^^^^ `Foo` is not an iterator | = note: the following trait bounds were not satisfied: `Foo: Iterator` diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 17d2292baaf68..0252ba2eb0460 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -5,6 +5,6 @@ use std::iter::once; fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); - //~^ ERROR the method + //~^ ERROR not an iterator //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index a8bcdf5efe91e..b1010171eb235 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -12,11 +12,11 @@ note: required by a bound in `filter` LL | P: FnMut(&Self::Item) -> bool, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter` -error[E0599]: the method `count` exists for struct `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied +error[E0599]: `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator --> $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | -------------- ^^^^^ method cannot be called on `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds + | -------------- ^^^^^ `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator | | | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` | doesn't satisfy `_: FnMut<(&&str,)>` diff --git a/src/tools/cargo b/src/tools/cargo index 3d6970d50e30e..65c82664263fe 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3d6970d50e30e797b8e26b2b9b1bdf92dc381f34 +Subproject commit 65c82664263feddc5fe2d424be0993c28d46377a diff --git a/triagebot.toml b/triagebot.toml index 276587e7f13fb..f6f1b918f061f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -73,6 +73,13 @@ Thanks! <3 """ label = "O-riscv" +[ping.fuchsia] +message = """\ +Hey friends of Fuchsia! This issue could use some guidance on how this should be +resolved/implemented on Fuchsia. Could one of you weigh in? +""" +label = "O-fuchsia" + [prioritize] label = "I-prioritize"