diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 97ef513cbcc63..39df803bbea30 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -164,7 +164,7 @@ impl dyn Any { // Get `TypeId` of the type this function is instantiated with. let t = TypeId::of::(); - // Get `TypeId` of the type in the trait object. + // Get `TypeId` of the type in the trait object (`self`). let concrete = self.type_id(); // Compare both `TypeId`s on equality. diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 844250f51a099..433076bb8342c 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -92,9 +92,6 @@ impl<'a> HashStable> for ty::RegionKind { ty::ReFree(ref free_region) => { free_region.hash_stable(hcx, hasher); } - ty::ReClosureBound(vid) => { - vid.hash_stable(hcx, hasher); - } ty::ReVar(..) | ty::RePlaceholder(..) => { bug!("StableHasher: unexpected region {:?}", *self) } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f665881ae4c22..8f06b9a69bd15 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -14,7 +14,7 @@ use rustc_hir as hir; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Pos, Span}; -use std::{any::Any, fmt}; +use std::{any::Any, fmt, mem}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { @@ -449,9 +449,6 @@ impl fmt::Debug for UndefinedBehaviorInfo { pub enum UnsupportedOpInfo { /// Free-form case. Only for errors that are never caught! Unsupported(String), - /// When const-prop encounters a situation it does not support, it raises this error. - /// This must not allocate for performance reasons (hence `str`, not `String`). - ConstPropUnsupported(&'static str), /// Accessing an unsupported foreign static. ReadForeignStatic(DefId), /// Could not find MIR for a function. @@ -470,9 +467,6 @@ impl fmt::Debug for UnsupportedOpInfo { use UnsupportedOpInfo::*; match self { Unsupported(ref msg) => write!(f, "{}", msg), - ConstPropUnsupported(ref msg) => { - write!(f, "Constant propagation encountered an unsupported situation: {}", msg) - } ReadForeignStatic(did) => { write!(f, "tried to read from foreign (extern) static {:?}", did) } @@ -494,8 +488,10 @@ impl fmt::Debug for UnsupportedOpInfo { pub enum ResourceExhaustionInfo { /// The stack grew too big. StackFrameLimitReached, - /// The program ran into an infinite loop. - InfiniteLoop, + /// The program ran for too long. + /// + /// The exact limit is set by the `const_eval_limit` attribute. + StepLimitReached, } impl fmt::Debug for ResourceExhaustionInfo { @@ -505,15 +501,36 @@ impl fmt::Debug for ResourceExhaustionInfo { StackFrameLimitReached => { write!(f, "reached the configured maximum number of stack frames") } - InfiniteLoop => write!( - f, - "duplicate interpreter state observed here, const evaluation will never \ - terminate" - ), + StepLimitReached => { + write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)") + } } } } +/// A trait to work around not having trait object upcasting. +pub trait AsAny: Any { + fn as_any(&self) -> &dyn Any; +} + +impl AsAny for T { + #[inline(always)] + fn as_any(&self) -> &dyn Any { + self + } +} + +/// A trait for machine-specific errors (or other "machine stop" conditions). +pub trait MachineStopType: AsAny + fmt::Debug + Send {} +impl MachineStopType for String {} + +impl dyn MachineStopType { + #[inline(always)] + pub fn downcast_ref(&self) -> Option<&T> { + self.as_any().downcast_ref() + } +} + pub enum InterpError<'tcx> { /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo), @@ -527,7 +544,7 @@ pub enum InterpError<'tcx> { ResourceExhaustion(ResourceExhaustionInfo), /// Stop execution for a machine-controlled reason. This is never raised by /// the core engine itself. - MachineStop(Box), + MachineStop(Box), } pub type InterpResult<'tcx, T = ()> = Result>; @@ -547,7 +564,7 @@ impl fmt::Debug for InterpError<'_> { InvalidProgram(ref msg) => write!(f, "{:?}", msg), UndefinedBehavior(ref msg) => write!(f, "{:?}", msg), ResourceExhaustion(ref msg) => write!(f, "{:?}", msg), - MachineStop(_) => bug!("unhandled MachineStop"), + MachineStop(ref msg) => write!(f, "{:?}", msg), } } } @@ -558,8 +575,9 @@ impl InterpError<'_> { /// waste of resources. pub fn allocates(&self) -> bool { match self { - InterpError::MachineStop(_) - | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) + // Zero-sized boxes do not allocate. + InterpError::MachineStop(b) => mem::size_of_val::(&**b) > 0, + InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true, _ => false, diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index a2f7a2d847e9f..bec848b17cafc 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -97,8 +97,8 @@ mod value; pub use self::error::{ struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo, - InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo, - UndefinedBehaviorInfo, UnsupportedOpInfo, + InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, + ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef}; diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs index 824cdfe55bfb6..8c81f5227d260 100644 --- a/src/librustc/mir/query.rs +++ b/src/librustc/mir/query.rs @@ -88,34 +88,35 @@ pub struct ConstQualifs { /// requirements are then verified and proved by the closure's /// creating function. This struct encodes those requirements. /// -/// The requirements are listed as being between various -/// `RegionVid`. The 0th region refers to `'static`; subsequent region -/// vids refer to the free regions that appear in the closure (or -/// generator's) type, in order of appearance. (This numbering is -/// actually defined by the `UniversalRegions` struct in the NLL -/// region checker. See for example -/// `UniversalRegions::closure_mapping`.) Note that we treat the free -/// regions in the closure's type "as if" they were erased, so their -/// precise identity is not important, only their position. +/// The requirements are listed as being between various `RegionVid`. The 0th +/// region refers to `'static`; subsequent region vids refer to the free +/// regions that appear in the closure (or generator's) type, in order of +/// appearance. (This numbering is actually defined by the `UniversalRegions` +/// struct in the NLL region checker. See for example +/// `UniversalRegions::closure_mapping`.) Note the free regions in the +/// closure's signature and captures are erased. /// /// Example: If type check produces a closure with the closure substs: /// /// ```text /// ClosureSubsts = [ -/// i8, // the "closure kind" -/// for<'x> fn(&'a &'x u32) -> &'x u32, // the "closure signature" -/// &'a String, // some upvar +/// 'a, // From the parent. +/// 'b, +/// i8, // the "closure kind" +/// for<'x> fn(&' &'x u32) -> &'x u32, // the "closure signature" +/// &' String, // some upvar /// ] /// ``` /// -/// here, there is one unique free region (`'a`) but it appears -/// twice. We would "renumber" each occurrence to a unique vid, as follows: +/// We would "renumber" each free region to a unique vid, as follows: /// /// ```text /// ClosureSubsts = [ -/// i8, // the "closure kind" -/// for<'x> fn(&'1 &'x u32) -> &'x u32, // the "closure signature" -/// &'2 String, // some upvar +/// '1, // From the parent. +/// '2, +/// i8, // the "closure kind" +/// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature" +/// &'4 String, // some upvar /// ] /// ``` /// @@ -124,14 +125,12 @@ pub struct ConstQualifs { /// can be extracted from its type and constrained to have the given /// outlives relationship. /// -/// In some cases, we have to record outlives requirements between -/// types and regions as well. In that case, if those types include -/// any regions, those regions are recorded as `ReClosureBound` -/// instances assigned one of these same indices. Those regions will -/// be substituted away by the creator. We use `ReClosureBound` in -/// that case because the regions must be allocated in the global -/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use -/// internally within the rest of the NLL code). +/// In some cases, we have to record outlives requirements between types and +/// regions as well. In that case, if those types include any regions, those +/// regions are recorded using their external names (`ReStatic`, +/// `ReEarlyBound`, `ReFree`). We use these because in a query response we +/// cannot use `ReVar` (which is what we use internally within the rest of the +/// NLL code). #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct ClosureRegionRequirements<'tcx> { /// The number of external regions defined on the closure. In our diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 3a95c573ca30c..58bff2f13eb70 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1574,7 +1574,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { ty::ReVar(_) | ty::ReScope(_) | ty::ReErased => false, - ty::ReStatic | ty::ReEmpty(_) | ty::ReClosureBound(_) => true, + ty::ReStatic | ty::ReEmpty(_) => true, } } @@ -1686,12 +1686,6 @@ impl FmtPrinter<'_, '_, F> { p!(write("'", ui)); return Ok(self); } - - // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => { - p!(write("{:?}", vid)); - return Ok(self); - } } p!(write("'_")); diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index e2fa03139110c..81be5b11143af 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -81,8 +81,6 @@ impl fmt::Debug for ty::RegionKind { match *self { ty::ReEarlyBound(ref data) => write!(f, "ReEarlyBound({}, {})", data.index, data.name), - ty::ReClosureBound(ref vid) => write!(f, "ReClosureBound({:?})", vid), - ty::ReLateBound(binder_id, ref bound_region) => { write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0c14580717f92..80ead3474e44e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1352,12 +1352,6 @@ pub enum RegionKind { /// Erased region, used by trait selection, in MIR and during codegen. ReErased, - - /// These are regions bound in the "defining type" for a - /// closure. They are used ONLY as part of the - /// `ClosureRegionRequirements` that are produced by MIR borrowck. - /// See `ClosureRegionRequirements` for more details. - ReClosureBound(RegionVid), } impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {} @@ -1567,7 +1561,6 @@ impl RegionKind { RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(), RegionKind::ReEmpty(_) => false, RegionKind::ReErased => false, - RegionKind::ReClosureBound(..) => false, } } @@ -1648,9 +1641,6 @@ impl RegionKind { ty::ReEmpty(_) | ty::ReStatic => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } - ty::ReClosureBound(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - } ty::ReLateBound(..) => { flags = flags | TypeFlags::HAS_RE_LATE_BOUND; } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1f512f1dde7d6..8ace84b7832e6 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1047,10 +1047,7 @@ pub fn needs_drop_components( // Foreign types can never have destructors. ty::Foreign(..) => Ok(SmallVec::new()), - // Pessimistically assume that all generators will require destructors - // as we don't know if a destructor is a noop or not until after the MIR - // state transformation pass. - ty::Generator(..) | ty::Dynamic(..) | ty::Error => Err(AlwaysRequiresDrop), + ty::Dynamic(..) | ty::Error => Err(AlwaysRequiresDrop), ty::Slice(ty) => needs_drop_components(ty, target_layout), ty::Array(elem_ty, size) => { @@ -1083,7 +1080,8 @@ pub fn needs_drop_components( | ty::Placeholder(..) | ty::Opaque(..) | ty::Infer(_) - | ty::Closure(..) => Ok(smallvec![ty]), + | ty::Closure(..) + | ty::Generator(..) => Ok(smallvec![ty]), } } diff --git a/src/librustc_error_codes/error_codes/E0452.md b/src/librustc_error_codes/error_codes/E0452.md index be3d573e10d2d..429813a7cdd4e 100644 --- a/src/librustc_error_codes/error_codes/E0452.md +++ b/src/librustc_error_codes/error_codes/E0452.md @@ -1,4 +1,6 @@ -An invalid lint attribute has been given. Erroneous code example: +An invalid lint attribute has been given. + +Erroneous code example: ```compile_fail,E0452 #![allow(foo = "")] // error: malformed lint attribute diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index 7b01f39d810b5..4d9a81d440695 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -336,10 +336,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { | ty::ReEmpty(_) | ty::RePlaceholder(..) | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r), - - ty::ReClosureBound(..) => { - bug!("closure bound region encountered during canonicalization"); - } } } diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 9d06e26d9bb3c..0f5d4d30a2385 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -581,10 +581,6 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { return Ok(r); } - ty::ReClosureBound(..) => { - span_bug!(self.span, "encountered unexpected ReClosureBound: {:?}", r,); - } - ty::RePlaceholder(..) | ty::ReVar(..) | ty::ReEmpty(_) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 78f97c40cbd12..a2ae4f53fb8f2 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -152,11 +152,6 @@ pub(super) fn note_and_explain_region( ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { (format!("lifetime {:?}", region), None) } - - // We shouldn't encounter an error message with ReClosureBound. - ty::ReClosureBound(..) => { - bug!("encountered unexpected ReClosureBound: {:?}", region,); - } }; emit_msg_span(err, prefix, description, span, suffix); diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index a454feea36b70..fa28cf5b45464 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -135,10 +135,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { // replace all free regions with 'erased self.tcx().lifetimes.re_erased } - - ty::ReClosureBound(..) => { - bug!("encountered unexpected region: {:?}", r,); - } } } diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index 821b9f72c0b20..d81c7454a0fe5 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -493,12 +493,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// term "concrete regions"). fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { let r = match (a, b) { - (&ty::ReClosureBound(..), _) - | (_, &ty::ReClosureBound(..)) - | (&ReLateBound(..), _) - | (_, &ReLateBound(..)) - | (&ReErased, _) - | (_, &ReErased) => { + (&ReLateBound(..), _) | (_, &ReLateBound(..)) | (&ReErased, _) | (_, &ReErased) => { bug!("cannot relate region: LUB({:?}, {:?})", a, b); } diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index 38475b02e5db8..72637f4544a35 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -798,7 +798,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { | ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT, ty::ReEmpty(ui) => ui, ty::RePlaceholder(placeholder) => placeholder.universe, - ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid), + ty::ReVar(vid) => self.var_universe(vid), ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 88f2284cd6154..66d9fe7e14988 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -349,6 +349,7 @@ impl MissingDoc { id: Option, attrs: &[ast::Attribute], sp: Span, + article: &'static str, desc: &'static str, ) { // If we're building a test harness, then warning about @@ -374,7 +375,7 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| has_doc(a)); if !has_doc { cx.struct_span_lint(MISSING_DOCS, cx.tcx.sess.source_map().def_span(sp), |lint| { - lint.build(&format!("missing documentation for {}", desc)).emit() + lint.build(&format!("missing documentation for {} {}", article, desc)).emit() }); } } @@ -398,7 +399,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "crate"); + self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "the", "crate"); for macro_def in krate.exported_macros { let has_doc = macro_def.attrs.iter().any(|a| has_doc(a)); @@ -413,12 +414,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) { - let desc = match it.kind { - hir::ItemKind::Fn(..) => "a function", - hir::ItemKind::Mod(..) => "a module", - hir::ItemKind::Enum(..) => "an enum", - hir::ItemKind::Struct(..) => "a struct", - hir::ItemKind::Union(..) => "a union", + match it.kind { hir::ItemKind::Trait(.., trait_item_refs) => { // Issue #11592: traits are always considered exported, even when private. if let hir::VisibilityKind::Inherited = it.vis.node { @@ -428,33 +424,39 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } return; } - "a trait" } - hir::ItemKind::TyAlias(..) => "a type alias", hir::ItemKind::Impl { of_trait: Some(ref trait_ref), items, .. } => { // If the trait is private, add the impl items to `private_traits` so they don't get // reported for missing docs. let real_trait = trait_ref.path.res.def_id(); if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(real_trait) { - match cx.tcx.hir().find(hir_id) { - Some(Node::Item(item)) => { - if let hir::VisibilityKind::Inherited = item.vis.node { - for impl_item_ref in items { - self.private_traits.insert(impl_item_ref.id.hir_id); - } + if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) { + if let hir::VisibilityKind::Inherited = item.vis.node { + for impl_item_ref in items { + self.private_traits.insert(impl_item_ref.id.hir_id); } } - _ => {} } } return; } - hir::ItemKind::Const(..) => "a constant", - hir::ItemKind::Static(..) => "a static", + + hir::ItemKind::TyAlias(..) + | hir::ItemKind::Fn(..) + | hir::ItemKind::Mod(..) + | hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::Const(..) + | hir::ItemKind::Static(..) => {} + _ => return, }; - self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, desc); + let def_id = cx.tcx.hir().local_def_id(it.hir_id); + let (article, desc) = cx.tcx.article_and_description(def_id); + + self.check_missing_docs_attrs(cx, Some(it.hir_id), &it.attrs, it.span, article, desc); } fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem<'_>) { @@ -462,17 +464,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { return; } - let desc = match trait_item.kind { - hir::TraitItemKind::Const(..) => "an associated constant", - hir::TraitItemKind::Fn(..) => "a trait method", - hir::TraitItemKind::Type(..) => "an associated type", - }; + let def_id = cx.tcx.hir().local_def_id(trait_item.hir_id); + let (article, desc) = cx.tcx.article_and_description(def_id); self.check_missing_docs_attrs( cx, Some(trait_item.hir_id), &trait_item.attrs, trait_item.span, + article, desc, ); } @@ -483,29 +483,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { return; } - let desc = match impl_item.kind { - hir::ImplItemKind::Const(..) => "an associated constant", - hir::ImplItemKind::Fn(..) => "a method", - hir::ImplItemKind::TyAlias(_) => "an associated type", - hir::ImplItemKind::OpaqueTy(_) => "an associated `impl Trait` type", - }; + let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); + let (article, desc) = cx.tcx.article_and_description(def_id); self.check_missing_docs_attrs( cx, Some(impl_item.hir_id), &impl_item.attrs, impl_item.span, + article, desc, ); } fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField<'_>) { if !sf.is_positional() { - self.check_missing_docs_attrs(cx, Some(sf.hir_id), &sf.attrs, sf.span, "a struct field") + self.check_missing_docs_attrs( + cx, + Some(sf.hir_id), + &sf.attrs, + sf.span, + "a", + "struct field", + ) } } fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant<'_>) { - self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, v.span, "a variant"); + self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, v.span, "a", "variant"); } } diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index c462f93414874..ee654431d8892 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -1,9 +1,10 @@ -use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location, ReadOnlyBodyAndCache}; +use rustc::mir::{self, ClearCrossCrate, Local, LocalInfo, Location}; use rustc::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; +use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::kw; use rustc_span::Span; @@ -338,10 +339,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match self.local_names[local] { Some(name) if !local_decl.from_compiler_desugaring() => { - let suggestion = match local_decl.local_info { + let label = match local_decl.local_info { LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(_), - )) => Some(suggest_ampmut_self(self.infcx.tcx, local_decl)), + )) => { + let (span, suggestion) = + suggest_ampmut_self(self.infcx.tcx, local_decl); + Some((true, span, suggestion)) + } LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( mir::VarBindingForm { @@ -349,13 +354,38 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { opt_ty_info, .. }, - ))) => Some(suggest_ampmut( - self.infcx.tcx, - self.body, - local, - local_decl, - opt_ty_info, - )), + ))) => { + // check if the RHS is from desugaring + let locations = self.body.find_assignments(local); + let opt_assignment_rhs_span = locations + .first() + .map(|&location| self.body.source_info(location).span); + let opt_desugaring_kind = + opt_assignment_rhs_span.and_then(|span| span.desugaring_kind()); + match opt_desugaring_kind { + // on for loops, RHS points to the iterator part + Some(DesugaringKind::ForLoop) => Some(( + false, + opt_assignment_rhs_span.unwrap(), + format!( + "this iterator yields `{SIGIL}` {DESC}s", + SIGIL = pointer_sigil, + DESC = pointer_desc + ), + )), + // don't create labels for compiler-generated spans + Some(_) => None, + None => { + let (span, suggestion) = suggest_ampmut( + self.infcx.tcx, + local_decl, + opt_assignment_rhs_span, + opt_ty_info, + ); + Some((true, span, suggestion)) + } + } + } LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( mir::VarBindingForm { @@ -365,7 +395,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ))) => { let pattern_span = local_decl.source_info.span; suggest_ref_mut(self.infcx.tcx, pattern_span) - .map(|replacement| (pattern_span, replacement)) + .map(|replacement| (true, pattern_span, replacement)) } LocalInfo::User(ClearCrossCrate::Clear) => { @@ -375,13 +405,22 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { _ => unreachable!(), }; - if let Some((err_help_span, suggested_code)) = suggestion { - err.span_suggestion( - err_help_span, - &format!("consider changing this to be a mutable {}", pointer_desc), - suggested_code, - Applicability::MachineApplicable, - ); + match label { + Some((true, err_help_span, suggested_code)) => { + err.span_suggestion( + err_help_span, + &format!( + "consider changing this to be a mutable {}", + pointer_desc + ), + suggested_code, + Applicability::MachineApplicable, + ); + } + Some((false, err_label_span, message)) => { + err.span_label(err_label_span, &message); + } + None => {} } err.span_label( span, @@ -581,14 +620,11 @@ fn suggest_ampmut_self<'tcx>( // by trying (3.), then (2.) and finally falling back on (1.). fn suggest_ampmut<'tcx>( tcx: TyCtxt<'tcx>, - body: ReadOnlyBodyAndCache<'_, 'tcx>, - local: Local, local_decl: &mir::LocalDecl<'tcx>, + opt_assignment_rhs_span: Option, opt_ty_info: Option, ) -> (Span, String) { - let locations = body.find_assignments(local); - if !locations.is_empty() { - let assignment_rhs_span = body.source_info(locations[0]).span; + if let Some(assignment_rhs_span) = opt_assignment_rhs_span { if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(|c: char| -> bool { c.is_whitespace() })) diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 164125a145b23..6756f476f6155 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -292,8 +292,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReEmpty(_) - | ty::ReErased - | ty::ReClosureBound(..) => None, + | ty::ReErased => None, } } diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index fe96b3e34a2a8..c8b0e59ebb117 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -940,8 +940,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// inference variables with some region from the closure /// signature -- this is not always possible, so this is a /// fallible process. Presuming we do find a suitable region, we - /// will represent it with a `ReClosureBound`, which is a - /// `RegionKind` variant that can be allocated in the gcx. + /// will use it's *external name*, which will be a `RegionKind` + /// variant that can be used in query responses such as + /// `ReEarlyBound`. fn try_promote_type_test_subject( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -991,14 +992,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { // find an equivalent. let upper_bound = self.non_local_universal_upper_bound(region_vid); if self.region_contains(region_vid, upper_bound) { - tcx.mk_region(ty::ReClosureBound(upper_bound)) + self.definitions[upper_bound].external_name.unwrap_or(r) } else { - // In the case of a failure, use a `ReVar` - // result. This will cause the `lift` later on to - // fail. + // In the case of a failure, use a `ReVar` result. This will + // cause the `has_local_value` later on to return `None`. r } }); + debug!("try_promote_type_test_subject: folded ty = {:?}", ty); // `has_local_value` will only be true if we failed to promote some region. @@ -2029,15 +2030,6 @@ pub trait ClosureRegionRequirementsExt<'tcx> { closure_def_id: DefId, closure_substs: SubstsRef<'tcx>, ) -> Vec>; - - fn subst_closure_mapping( - &self, - tcx: TyCtxt<'tcx>, - closure_mapping: &IndexVec>, - value: &T, - ) -> T - where - T: TypeFoldable<'tcx>; } impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> { @@ -2094,7 +2086,6 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx } ClosureOutlivesSubject::Ty(ty) => { - let ty = self.subst_closure_mapping(tcx, closure_mapping, &ty); debug!( "apply_requirements: ty={:?} \ outlived_region={:?} \ @@ -2107,22 +2098,4 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx }) .collect() } - - fn subst_closure_mapping( - &self, - tcx: TyCtxt<'tcx>, - closure_mapping: &IndexVec>, - value: &T, - ) -> T - where - T: TypeFoldable<'tcx>, - { - tcx.fold_regions(value, &mut false, |r, _depth| { - if let ty::ReClosureBound(vid) = r { - closure_mapping[*vid] - } else { - bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r) - } - }) - } } diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 87d0424ece944..ab88a92ea7bc2 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -3,7 +3,6 @@ use rustc::ty::layout::HasTyCtxt; use rustc::ty::{self, Ty}; use std::borrow::{Borrow, Cow}; use std::collections::hash_map::Entry; -use std::convert::TryFrom; use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; @@ -13,13 +12,13 @@ use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; use crate::interpret::{ - self, snapshot, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, - MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy, + PlaceTy, Pointer, Scalar, }; use super::error::*; -impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { +impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter> { /// Evaluate a const function where all arguments (if any) are zero-sized types. /// The evaluation is memoized thanks to the query system. /// @@ -86,22 +85,13 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { } } -/// The number of steps between loop detector snapshots. -/// Should be a power of two for performance reasons. -const DETECTOR_SNAPSHOT_PERIOD: isize = 256; - -// Extra machine state for CTFE, and the Machine instance -pub struct CompileTimeInterpreter<'mir, 'tcx> { - /// When this value is negative, it indicates the number of interpreter - /// steps *until* the loop detector is enabled. When it is positive, it is - /// the number of steps after the detector has been enabled modulo the loop - /// detector period. - pub(super) steps_since_detector_enabled: isize, - - pub(super) is_detector_enabled: bool, - - /// Extra state to detect loops. - pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>, +/// Extra machine state for CTFE, and the Machine instance +pub struct CompileTimeInterpreter { + /// For now, the number of terminators that can be evaluated before we throw a resource + /// exhuastion error. + /// + /// Setting this to `0` disables the limit and allows the interpreter to run forever. + pub steps_remaining: usize, } #[derive(Copy, Clone, Debug)] @@ -110,16 +100,9 @@ pub struct MemoryExtra { pub(super) can_access_statics: bool, } -impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { +impl CompileTimeInterpreter { pub(super) fn new(const_eval_limit: usize) -> Self { - let steps_until_detector_enabled = - isize::try_from(const_eval_limit).unwrap_or(std::isize::MAX); - - CompileTimeInterpreter { - loop_detector: Default::default(), - steps_since_detector_enabled: -steps_until_detector_enabled, - is_detector_enabled: const_eval_limit != 0, - } + CompileTimeInterpreter { steps_remaining: const_eval_limit } } } @@ -173,8 +156,7 @@ impl interpret::AllocMap for FxHashMap { } } -crate type CompileTimeEvalContext<'mir, 'tcx> = - InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>; +crate type CompileTimeEvalContext<'mir, 'tcx> = InterpCx<'mir, 'tcx, CompileTimeInterpreter>; impl interpret::MayLeak for ! { #[inline(always)] @@ -184,7 +166,7 @@ impl interpret::MayLeak for ! { } } -impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> { +impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter { type MemoryKinds = !; type PointerTag = (); type ExtraFnVal = !; @@ -345,26 +327,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { - if !ecx.machine.is_detector_enabled { + // The step limit has already been hit in a previous call to `before_terminator`. + if ecx.machine.steps_remaining == 0 { return Ok(()); } - { - let steps = &mut ecx.machine.steps_since_detector_enabled; - - *steps += 1; - if *steps < 0 { - return Ok(()); - } - - *steps %= DETECTOR_SNAPSHOT_PERIOD; - if *steps != 0 { - return Ok(()); - } + ecx.machine.steps_remaining -= 1; + if ecx.machine.steps_remaining == 0 { + throw_exhaust!(StepLimitReached) } - let span = ecx.frame().span; - ecx.machine.loop_detector.observe_and_analyze(*ecx.tcx, span, &ecx.memory, &ecx.stack[..]) + Ok(()) } #[inline(always)] diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 5b2cd89a12284..277a77af3fd56 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -112,25 +112,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> } } -// FIXME: Really we shouldn't clone memory, ever. Snapshot machinery should instead -// carefully copy only the reachable parts. -impl<'mir, 'tcx, M> Clone for Memory<'mir, 'tcx, M> -where - M: Machine<'mir, 'tcx, PointerTag = (), AllocExtra = ()>, - M::MemoryExtra: Copy, - M::MemoryMap: AllocMap, Allocation)>, -{ - fn clone(&self) -> Self { - Memory { - alloc_map: self.alloc_map.clone(), - extra_fn_ptr_map: self.extra_fn_ptr_map.clone(), - dead_alloc_map: self.dead_alloc_map.clone(), - extra: self.extra, - tcx: self.tcx, - } - } -} - impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self { Memory { diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index c3fd968276577..3063a99886b7b 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -9,7 +9,6 @@ mod memory; mod operand; mod operator; mod place; -pub(crate) mod snapshot; // for const_eval mod step; mod terminator; mod traits; diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs deleted file mode 100644 index ee45179fd8b31..0000000000000 --- a/src/librustc_mir/interpret/snapshot.rs +++ /dev/null @@ -1,420 +0,0 @@ -//! This module contains the machinery necessary to detect infinite loops -//! during const-evaluation by taking snapshots of the state of the interpreter -//! at regular intervals. - -// This lives in `interpret` because it needs access to all sots of private state. However, -// it is not used by the general miri engine, just by CTFE. - -use std::hash::{Hash, Hasher}; - -use rustc::ich::StableHashingContextProvider; -use rustc::mir; -use rustc::mir::interpret::{ - AllocId, Allocation, InterpResult, Pointer, Relocations, Scalar, UndefMask, -}; - -use rustc::ty::layout::{Align, Size}; -use rustc::ty::{self, TyCtxt}; -use rustc_ast::ast::Mutability; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_index::vec::IndexVec; -use rustc_macros::HashStable; -use rustc_span::source_map::Span; - -use super::eval_context::{LocalState, StackPopCleanup}; -use super::{ - Frame, Immediate, LocalValue, MemPlace, MemPlaceMeta, Memory, Operand, Place, ScalarMaybeUndef, -}; -use crate::const_eval::CompileTimeInterpreter; - -#[derive(Default)] -pub(crate) struct InfiniteLoopDetector<'mir, 'tcx> { - /// The set of all `InterpSnapshot` *hashes* observed by this detector. - /// - /// When a collision occurs in this table, we store the full snapshot in - /// `snapshots`. - hashes: FxHashSet, - - /// The set of all `InterpSnapshot`s observed by this detector. - /// - /// An `InterpSnapshot` will only be fully cloned once it has caused a - /// collision in `hashes`. As a result, the detector must observe at least - /// *two* full cycles of an infinite loop before it triggers. - snapshots: FxHashSet>, -} - -impl<'mir, 'tcx> InfiniteLoopDetector<'mir, 'tcx> { - pub fn observe_and_analyze( - &mut self, - tcx: TyCtxt<'tcx>, - span: Span, - memory: &Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, - stack: &[Frame<'mir, 'tcx>], - ) -> InterpResult<'tcx, ()> { - // Compute stack's hash before copying anything - let mut hcx = tcx.get_stable_hashing_context(); - let mut hasher = StableHasher::new(); - stack.hash_stable(&mut hcx, &mut hasher); - let hash = hasher.finish::(); - - // Check if we know that hash already - if self.hashes.is_empty() { - // FIXME(#49980): make this warning a lint - tcx.sess.span_warn( - span, - "Constant evaluating a complex constant, this might take some time", - ); - } - if self.hashes.insert(hash) { - // No collision - return Ok(()); - } - - // We need to make a full copy. NOW things that to get really expensive. - info!("snapshotting the state of the interpreter"); - - if self.snapshots.insert(InterpSnapshot::new(memory, stack)) { - // Spurious collision or first cycle - return Ok(()); - } - - // Second cycle - throw_exhaust!(InfiniteLoop) - } -} - -trait SnapshotContext<'a> { - fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>; -} - -/// Taking a snapshot of the evaluation context produces a view of -/// the state of the interpreter that is invariant to `AllocId`s. -trait Snapshot<'a, Ctx: SnapshotContext<'a>> { - type Item; - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item; -} - -macro_rules! __impl_snapshot_field { - ($field:ident, $ctx:expr) => { - $field.snapshot($ctx) - }; - ($field:ident, $ctx:expr, $delegate:expr) => { - $delegate - }; -} - -// This assumes the type has two type parameters, first for the tag (set to `()`), -// then for the id -macro_rules! impl_snapshot_for { - (enum $enum_name:ident { - $( $variant:ident $( ( $($field:ident $(-> $delegate:expr)?),* ) )? ),* $(,)? - }) => { - - impl<'a, Ctx> self::Snapshot<'a, Ctx> for $enum_name - where Ctx: self::SnapshotContext<'a>, - { - type Item = $enum_name<(), AllocIdSnapshot<'a>>; - - #[inline] - fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item { - match *self { - $( - $enum_name::$variant $( ( $(ref $field),* ) )? => { - $enum_name::$variant $( - ( $( __impl_snapshot_field!($field, __ctx $(, $delegate)?) ),* ) - )? - } - )* - } - } - } - }; - - (struct $struct_name:ident { $($field:ident $(-> $delegate:expr)?),* $(,)? }) => { - impl<'a, Ctx> self::Snapshot<'a, Ctx> for $struct_name - where Ctx: self::SnapshotContext<'a>, - { - type Item = $struct_name<(), AllocIdSnapshot<'a>>; - - #[inline] - fn snapshot(&self, __ctx: &'a Ctx) -> Self::Item { - let $struct_name { - $(ref $field),* - } = *self; - - $struct_name { - $( $field: __impl_snapshot_field!($field, __ctx $(, $delegate)?) ),* - } - } - } - }; -} - -impl<'a, Ctx, T> Snapshot<'a, Ctx> for Option -where - Ctx: SnapshotContext<'a>, - T: Snapshot<'a, Ctx>, -{ - type Item = Option<>::Item>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - match self { - Some(x) => Some(x.snapshot(ctx)), - None => None, - } - } -} - -#[derive(Eq, PartialEq)] -struct AllocIdSnapshot<'a>(Option>); - -impl<'a, Ctx> Snapshot<'a, Ctx> for AllocId -where - Ctx: SnapshotContext<'a>, -{ - type Item = AllocIdSnapshot<'a>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - AllocIdSnapshot(ctx.resolve(self).map(|alloc| alloc.snapshot(ctx))) - } -} - -impl_snapshot_for!(struct Pointer { - alloc_id, - offset -> *offset, // just copy offset verbatim - tag -> *tag, // just copy tag -}); - -impl<'a, Ctx> Snapshot<'a, Ctx> for Scalar -where - Ctx: SnapshotContext<'a>, -{ - type Item = Scalar<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - match self { - Scalar::Ptr(p) => Scalar::Ptr(p.snapshot(ctx)), - Scalar::Raw { size, data } => Scalar::Raw { data: *data, size: *size }, - } - } -} - -impl_snapshot_for!( - enum ScalarMaybeUndef { - Scalar(s), - Undef, - } -); - -impl_snapshot_for!( - enum MemPlaceMeta { - Meta(s), - None, - Poison, - } -); - -impl_snapshot_for!(struct MemPlace { - ptr, - meta, - align -> *align, // just copy alignment verbatim -}); - -impl<'a, Ctx> Snapshot<'a, Ctx> for Place -where - Ctx: SnapshotContext<'a>, -{ - type Item = Place<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - match self { - Place::Ptr(p) => Place::Ptr(p.snapshot(ctx)), - - Place::Local { frame, local } => Place::Local { frame: *frame, local: *local }, - } - } -} - -impl_snapshot_for!( - enum Immediate { - Scalar(s), - ScalarPair(s, t), - } -); - -impl_snapshot_for!( - enum Operand { - Immediate(v), - Indirect(m), - } -); - -impl_snapshot_for!( - enum LocalValue { - Dead, - Uninitialized, - Live(v), - } -); - -impl<'a, Ctx> Snapshot<'a, Ctx> for Relocations -where - Ctx: SnapshotContext<'a>, -{ - type Item = Relocations<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - Relocations::from_presorted( - self.iter().map(|(size, ((), id))| (*size, ((), id.snapshot(ctx)))).collect(), - ) - } -} - -#[derive(Eq, PartialEq)] -struct AllocationSnapshot<'a> { - bytes: &'a [u8], - relocations: Relocations<(), AllocIdSnapshot<'a>>, - undef_mask: &'a UndefMask, - align: &'a Align, - size: &'a Size, - mutability: &'a Mutability, -} - -impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation -where - Ctx: SnapshotContext<'a>, -{ - type Item = AllocationSnapshot<'a>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let Allocation { size, align, mutability, extra: (), .. } = self; - - let all_bytes = 0..self.len(); - // This 'inspect' is okay since following access respects undef and relocations. This does - // influence interpreter exeuction, but only to detect the error of cycles in evaluation - // dependencies. - let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes); - - let undef_mask = self.undef_mask(); - let relocations = self.relocations(); - - AllocationSnapshot { - bytes, - undef_mask, - align, - size, - mutability, - relocations: relocations.snapshot(ctx), - } - } -} - -#[derive(Eq, PartialEq)] -struct FrameSnapshot<'a, 'tcx> { - instance: ty::Instance<'tcx>, - span: Span, - return_to_block: &'a StackPopCleanup, - return_place: Option>>, - locals: IndexVec>>, - block: Option, - stmt: usize, -} - -impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx> -where - Ctx: SnapshotContext<'a>, -{ - type Item = FrameSnapshot<'a, 'tcx>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let Frame { - body: _, - instance, - span, - return_to_block, - return_place, - locals, - block, - stmt, - extra: _, - } = self; - - FrameSnapshot { - instance: *instance, - span: *span, - return_to_block, - block: *block, - stmt: *stmt, - return_place: return_place.map(|r| r.snapshot(ctx)), - locals: locals.iter().map(|local| local.snapshot(ctx)).collect(), - } - } -} - -impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalState<'tcx> -where - Ctx: SnapshotContext<'a>, -{ - type Item = LocalValue<(), AllocIdSnapshot<'a>>; - - fn snapshot(&self, ctx: &'a Ctx) -> Self::Item { - let LocalState { value, layout: _ } = self; - value.snapshot(ctx) - } -} - -impl<'b, 'mir, 'tcx> SnapshotContext<'b> - for Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> -{ - fn resolve(&'b self, id: &AllocId) -> Option<&'b Allocation> { - self.get_raw(*id).ok() - } -} - -/// The virtual machine state during const-evaluation at a given point in time. -/// We assume the `CompileTimeInterpreter` has no interesting extra state that -/// is worth considering here. -#[derive(HashStable)] -struct InterpSnapshot<'mir, 'tcx> { - // Not hashing memory: Avoid hashing memory all the time during execution - #[stable_hasher(ignore)] - memory: Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, - stack: Vec>, -} - -impl InterpSnapshot<'mir, 'tcx> { - fn new( - memory: &Memory<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>, - stack: &[Frame<'mir, 'tcx>], - ) -> Self { - InterpSnapshot { memory: memory.clone(), stack: stack.into() } - } - - // Used to compare two snapshots - fn snapshot(&'b self) -> Vec> { - // Start with the stack, iterate and recursively snapshot - self.stack.iter().map(|frame| frame.snapshot(&self.memory)).collect() - } -} - -impl<'mir, 'tcx> Hash for InterpSnapshot<'mir, 'tcx> { - fn hash(&self, state: &mut H) { - // Implement in terms of hash stable, so that k1 == k2 -> hash(k1) == hash(k2) - let mut hcx = self.memory.tcx.get_stable_hashing_context(); - let mut hasher = StableHasher::new(); - self.hash_stable(&mut hcx, &mut hasher); - hasher.finish::().hash(state) - } -} - -impl<'mir, 'tcx> Eq for InterpSnapshot<'mir, 'tcx> {} - -impl<'mir, 'tcx> PartialEq for InterpSnapshot<'mir, 'tcx> { - fn eq(&self, other: &Self) -> bool { - // FIXME: This looks to be a *ridiculously expensive* comparison operation. - // Doesn't this make tons of copies? Either `snapshot` is very badly named, - // or it does! - self.snapshot() == other.snapshot() - } -} diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a19901f37787e..8899f12b15361 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -39,6 +39,24 @@ use crate::transform::{MirPass, MirSource}; /// The maximum number of bytes that we'll allocate space for a return value. const MAX_ALLOC_LIMIT: u64 = 1024; +/// Macro for machine-specific `InterpError` without allocation. +/// (These will never be shown to the user, but they help diagnose ICEs.) +macro_rules! throw_machine_stop_str { + ($($tt:tt)*) => {{ + // We make a new local type for it. The type itself does not carry any information, + // but its vtable (for the `MachineStopType` trait) does. + struct Zst; + // Debug-printing this type shows the desired string. + impl std::fmt::Debug for Zst { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, $($tt)*) + } + } + impl rustc::mir::interpret::MachineStopType for Zst {} + throw_machine_stop!(Zst) + }}; +} + pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { @@ -192,7 +210,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _ret: Option<(PlaceTy<'tcx>, BasicBlock)>, _unwind: Option, ) -> InterpResult<'tcx> { - throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp")) + throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp") } fn assert_panic( @@ -204,7 +222,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { } fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { - throw_unsup!(ConstPropUnsupported("ptr-to-int casts aren't supported in ConstProp")) + throw_unsup!(ReadPointerAsBytes) } fn binary_ptr_op( @@ -214,10 +232,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _right: ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { // We can't do this because aliasing of memory can differ between const eval and llvm - throw_unsup!(ConstPropUnsupported( - "pointer arithmetic or comparisons aren't supported \ - in ConstProp" - )) + throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } #[inline(always)] @@ -238,7 +253,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - throw_unsup!(ConstPropUnsupported("can't const prop `box` keyword")) + throw_machine_stop_str!("can't const prop heap allocations") } fn access_local( @@ -249,7 +264,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { let l = &frame.locals[local]; if l.value == LocalValue::Uninitialized { - throw_unsup!(ConstPropUnsupported("tried to access an uninitialized local")); + throw_machine_stop_str!("tried to access an uninitialized local") } l.access() @@ -262,7 +277,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { // if the static allocation is mutable or if it has relocations (it may be legal to mutate // the memory behind that in the future), then we can't const prop it if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 { - throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp")); + throw_machine_stop_str!("can't eval mutable statics in ConstProp") } Ok(()) diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index f8a4e024605aa..9ad6e792c28ba 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -386,6 +386,12 @@ declare_lint! { "failures in resolving intra-doc link targets" } +declare_lint! { + pub MISSING_CRATE_LEVEL_DOCS, + Allow, + "detects crates with no crate-level documentation" +} + declare_lint! { pub MISSING_DOC_CODE_EXAMPLES, Allow, @@ -547,6 +553,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, INTRA_DOC_LINK_RESOLUTION_FAILURE, + MISSING_CRATE_LEVEL_DOCS, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, WHERE_CLAUSES_OBJECT_SAFETY, diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 9cd97c34f3ba4..30189d189f2ed 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -816,11 +816,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { // The regions that we expect from borrow checking. ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} - ty::ReEmpty(_) - | ty::RePlaceholder(_) - | ty::ReVar(_) - | ty::ReScope(_) - | ty::ReClosureBound(_) => { + ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) | ty::ReScope(_) => { // All of the regions in the type should either have been // erased by writeback, or mapped back to named regions by // borrow checking. diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index 37af8168f87d9..f8149cdce4d30 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -99,6 +99,23 @@ where } } + ty::Generator(_, substs, _) => { + let substs = substs.as_generator(); + for upvar_ty in substs.upvar_tys() { + queue_type(self, upvar_ty); + } + + let witness = substs.witness(); + let interior_tys = match &witness.kind { + ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys), + _ => bug!(), + }; + + for interior_ty in interior_tys { + queue_type(self, interior_ty); + } + } + // Check for a `Drop` impl and whether this is a union or // `ManuallyDrop`. If it's a struct or enum without a `Drop` // impl then check whether the field types need `Drop`. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e812fa81e6252..cccf866ae1638 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -20,7 +20,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{walk_generics, Visitor}; use rustc_hir::print; use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; @@ -838,18 +838,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }, ); - if !inferred_params.is_empty() { - // We always collect the spans for placeholder types when evaluating `fn`s, but we - // only want to emit an error complaining about them if infer types (`_`) are not - // allowed. `allow_ty_infer` gates this behavior. - crate::collect::placeholder_type_error( - tcx, - inferred_params[0], - &[], - inferred_params, - false, - ); - } self.complain_about_missing_type_params( missing_type_params, @@ -2747,7 +2735,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::BareFn(ref bf) => { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl, &[], None)) + tcx.mk_fn_ptr(self.ty_of_fn( + bf.unsafety, + bf.abi, + &bf.decl, + &hir::Generics::empty(), + None, + )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) @@ -2930,7 +2924,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, - generic_params: &[hir::GenericParam<'_>], + generics: &hir::Generics<'_>, ident_span: Option, ) -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); @@ -2942,6 +2936,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for ty in decl.inputs { visitor.visit_ty(ty); } + walk_generics(&mut visitor, generics); + let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let output_ty = match decl.output { hir::FnRetTy::Return(ref output) => { @@ -2963,7 +2959,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { crate::collect::placeholder_type_error( tcx, ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP), - generic_params, + &generics.params[..], visitor.0, ident_span.is_some(), ); @@ -2989,8 +2985,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.sess, decl.output.span(), E0581, - "return type references {} \ - which is not constrained by the fn input types", + "return type references {} which is not constrained by the fn input types", lifetime_name ); if let ty::BrAnon(_) = *br { @@ -3001,8 +2996,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // though we can easily give a hint that ought to be // relevant. err.note( - "lifetimes appearing in an associated type \ - are not considered constrained", + "lifetimes appearing in an associated type are not considered constrained", ); } err.emit(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3aa76a46f60f2..c8374cf03972e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1003,7 +1003,14 @@ fn typeck_tables_of_with_fallback<'tcx>( let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl, &[], None) + AstConv::ty_of_fn( + &fcx, + header.unsafety, + header.abi, + decl, + &hir::Generics::empty(), + None, + ) } else { tcx.fn_sig(def_id) }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f1e6655e8fed8..8136417de0387 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1486,7 +1486,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { sig.header.unsafety, sig.header.abi, &sig.decl, - &generics.params[..], + &generics, Some(ident.span), ), } @@ -1497,14 +1497,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ident, generics, .. - }) => AstConv::ty_of_fn( - &icx, - header.unsafety, - header.abi, - decl, - &generics.params[..], - Some(ident.span), - ), + }) => { + AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span)) + } ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); @@ -2127,7 +2122,14 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; - let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl, &[], None); + let fty = AstConv::ty_of_fn( + &ItemCtxt::new(tcx, def_id), + unsafety, + abi, + decl, + &hir::Generics::empty(), + None, + ); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 0cc322f8c2d3d..e1bd78e5113d1 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -170,7 +170,6 @@ fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool { // These regions don't appear in types from type declarations: RegionKind::ReErased - | RegionKind::ReClosureBound(..) | RegionKind::ReScope(..) | RegionKind::ReVar(..) | RegionKind::RePlaceholder(..) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 54f84272ae8e0..11612066d44b2 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -449,7 +449,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::ReFree(..) - | ty::ReClosureBound(..) | ty::ReScope(..) | ty::ReVar(..) | ty::RePlaceholder(..) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e69d4ddc2d01b..7dfcf0a637eb3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -450,7 +450,6 @@ impl Clean> for ty::RegionKind { | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReEmpty(_) - | ty::ReClosureBound(_) | ty::ReErased => { debug!("cannot clean region {:?}", self); None diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index f0b9ad2852f51..fe3a9b6b3dcdd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -249,6 +249,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; + let no_crate_level_docs = rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS.name; // In addition to those specific lints, we also need to whitelist those given through // command line, otherwise they'll get ignored and we don't want that. @@ -258,6 +259,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt missing_docs.to_owned(), missing_doc_example.to_owned(), private_doc_tests.to_owned(), + no_crate_level_docs.to_owned(), ]; whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); @@ -411,10 +413,28 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut krate = clean::krate(&mut ctxt); + if let Some(ref m) = krate.module { + if let None | Some("") = m.doc_value() { + let help = "The following guide may be of use:\n\ + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ + .html"; + tcx.struct_lint_node( + rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS, + ctxt.as_local_hir_id(m.def_id).unwrap(), + |lint| { + let mut diag = lint.build( + "no documentation found for this crate's top-level module", + ); + diag.help(help); + diag.emit(); + }, + ); + } + } + fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) { let mut msg = diag.struct_warn(&format!( - "the `#![doc({})]` attribute is \ - considered deprecated", + "the `#![doc({})]` attribute is considered deprecated", name )); msg.warn( diff --git a/src/test/mir-opt/generator-drop-cleanup.rs b/src/test/mir-opt/generator-drop-cleanup.rs index 278dc49c92605..c4742e8156938 100644 --- a/src/test/mir-opt/generator-drop-cleanup.rs +++ b/src/test/mir-opt/generator-drop-cleanup.rs @@ -5,6 +5,7 @@ fn main() { let gen = || { + let _s = String::new(); yield; }; } @@ -13,35 +14,49 @@ fn main() { // START rustc.main-{{closure}}.generator_drop.0.mir // bb0: { -// _7 = discriminant((*_1)); -// switchInt(move _7) -> [0u32: bb4, 3u32: bb7, otherwise: bb8]; +// _9 = discriminant((*_1)); +// switchInt(move _9) -> [0u32: bb7, 3u32: bb11, otherwise: bb12]; // } -// bb1: { -// StorageDead(_4); -// StorageDead(_3); -// goto -> bb5; +// bb1 (cleanup): { +// resume; // } -// bb2: { -// return; +// bb2 (cleanup): { +// nop; +// goto -> bb8; // } // bb3: { -// return; +// StorageDead(_5); +// StorageDead(_4); +// drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb4, unwind: bb2]; // } // bb4: { -// goto -> bb6; +// nop; +// goto -> bb9; // } // bb5: { -// goto -> bb2; +// return; // } // bb6: { -// goto -> bb3; +// return; // } // bb7: { -// StorageLive(_3); -// StorageLive(_4); +// goto -> bb10; +// } +// bb8 (cleanup): { // goto -> bb1; // } -// bb8: { +// bb9: { +// goto -> bb5; +// } +// bb10: { +// goto -> bb6; +// } +// bb11: { +// StorageLive(_4); +// StorageLive(_5); +// goto -> bb3; +// } +// bb12: { // return; // } // END rustc.main-{{closure}}.generator_drop.0.mir diff --git a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr index f0a13b70b977f..821e6b99f7b8f 100644 --- a/src/test/rustdoc-ui/deny-missing-docs-crate.stderr +++ b/src/test/rustdoc-ui/deny-missing-docs-crate.stderr @@ -1,4 +1,4 @@ -error: missing documentation for crate +error: missing documentation for the crate --> $DIR/deny-missing-docs-crate.rs:1:1 | LL | / #![deny(missing_docs)] diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs new file mode 100644 index 0000000000000..152a7cd88bcb1 --- /dev/null +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs @@ -0,0 +1,3 @@ +#![deny(missing_crate_level_docs)] + +pub fn foo() {} diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr new file mode 100644 index 0000000000000..6e7e2fb3eb73f --- /dev/null +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr @@ -0,0 +1,12 @@ +error: no documentation found for this crate's top-level module + | +note: the lint level is defined here + --> $DIR/no-crate-level-doc-lint.rs:1:9 + | +LL | #![deny(missing_crate_level_docs)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = help: The following guide may be of use: + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html + +error: aborting due to previous error + diff --git a/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs new file mode 100644 index 0000000000000..f6d0e9e04d321 --- /dev/null +++ b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs @@ -0,0 +1,11 @@ +// Regression test for #69789: rustc generated an invalid suggestion +// when `&` reference from `&mut` iterator is mutated. + +fn main() { + for item in &mut std::iter::empty::<&'static ()>() { + //~^ NOTE this iterator yields `&` references + *item = (); + //~^ ERROR cannot assign + //~| NOTE cannot be written + } +} diff --git a/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr new file mode 100644 index 0000000000000..d2865ffd196a5 --- /dev/null +++ b/src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr @@ -0,0 +1,12 @@ +error[E0594]: cannot assign to `*item` which is behind a `&` reference + --> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9 + | +LL | for item in &mut std::iter::empty::<&'static ()>() { + | -------------------------------------- this iterator yields `&` references +LL | +LL | *item = (); + | ^^^^^^^^^^ `item` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs index af5e7658d48d2..c8de259354eac 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.rs +++ b/src/test/ui/consts/const-eval/infinite_loop.rs @@ -2,7 +2,6 @@ fn main() { // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). // The value of `n` will loop indefinitely (4 - 2 - 1 - 4). let _ = [(); { - //~^ WARNING Constant evaluating a complex constant, this might take some time let mut n = 113383; // #20 in https://oeis.org/A006884 while n != 0 { //~^ ERROR `while` is not allowed in a `const` diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr index e04c31cf39782..ebdb73c446791 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.stderr +++ b/src/test/ui/consts/const-eval/infinite_loop.stderr @@ -1,5 +1,5 @@ error[E0658]: `while` is not allowed in a `const` - --> $DIR/infinite_loop.rs:7:9 + --> $DIR/infinite_loop.rs:6:9 | LL | / while n != 0 { LL | | @@ -14,7 +14,7 @@ LL | | } = help: add `#![feature(const_if_match)]` to the crate attributes to enable error[E0658]: `if` is not allowed in a `const` - --> $DIR/infinite_loop.rs:9:17 + --> $DIR/infinite_loop.rs:8:17 | LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,24 +22,11 @@ LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; = note: see issue #49146 for more information = help: add `#![feature(const_if_match)]` to the crate attributes to enable -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/infinite_loop.rs:4:18 - | -LL | let _ = [(); { - | __________________^ -LL | | -LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 -LL | | while n != 0 { -... | -LL | | n -LL | | }]; - | |_____^ - error[E0080]: evaluation of constant value failed - --> $DIR/infinite_loop.rs:9:20 + --> $DIR/infinite_loop.rs:8:20 | LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; - | ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate + | ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/issue-52475.rs b/src/test/ui/consts/const-eval/issue-52475.rs index 3788167f44902..869f0b981af7d 100644 --- a/src/test/ui/consts/const-eval/issue-52475.rs +++ b/src/test/ui/consts/const-eval/issue-52475.rs @@ -1,6 +1,5 @@ fn main() { let _ = [(); { - //~^ WARNING Constant evaluating a complex constant, this might take some time let mut x = &0; let mut n = 0; while n < 5 { diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr index 31d87925b2cfc..b069537ead963 100644 --- a/src/test/ui/consts/const-eval/issue-52475.stderr +++ b/src/test/ui/consts/const-eval/issue-52475.stderr @@ -1,5 +1,5 @@ error[E0658]: `while` is not allowed in a `const` - --> $DIR/issue-52475.rs:6:9 + --> $DIR/issue-52475.rs:5:9 | LL | / while n < 5 { LL | | @@ -12,24 +12,11 @@ LL | | } = help: add `#![feature(const_loop)]` to the crate attributes to enable = help: add `#![feature(const_if_match)]` to the crate attributes to enable -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/issue-52475.rs:2:18 - | -LL | let _ = [(); { - | __________________^ -LL | | -LL | | let mut x = &0; -LL | | let mut n = 0; -... | -LL | | 0 -LL | | }]; - | |_____^ - error[E0080]: evaluation of constant value failed - --> $DIR/issue-52475.rs:8:17 + --> $DIR/issue-52475.rs:7:17 | LL | n = (n + 1) % 5; - | ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate + | ^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs index 4ed908312fb6d..34abcdf08dae0 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs @@ -1,15 +1,21 @@ // check-pass + #![feature(const_eval_limit)] -#![const_eval_limit="1000"] +#![feature(const_loop, const_if_match)] -const CONSTANT: usize = limit(); +// This needs to be higher than the number of loop iterations since each pass through the loop may +// hit more than one terminator. +#![const_eval_limit="4000"] -fn main() { - assert_eq!(CONSTANT, 1764); -} +const X: usize = { + let mut x = 0; + while x != 1000 { + x += 1; + } -const fn limit() -> usize { - let x = 42; + x +}; - x * 42 +fn main() { + assert_eq!(X, 1000); } diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs index d962398d4136e..b45aca0b13e42 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs @@ -1,21 +1,18 @@ -// ignore-tidy-linelength -// only-x86_64 -// check-pass -// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels -// optimize away the const function -// compile-flags:-Copt-level=0 #![feature(const_eval_limit)] -#![const_eval_limit="2"] +#![feature(const_loop, const_if_match)] -const CONSTANT: usize = limit(); -//~^ WARNING Constant evaluating a complex constant, this might take some time +#![const_eval_limit="500"] -fn main() { - assert_eq!(CONSTANT, 1764); -} +const X: usize = { + let mut x = 0; + while x != 1000 { + //~^ ERROR any use of this value will cause an error + x += 1; + } -const fn limit() -> usize { //~ WARNING Constant evaluating a complex constant, this might take some time - let x = 42; + x +}; - x * 42 +fn main() { + assert_eq!(X, 1000); } diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr index e0871ff718561..be522dd6d5d5a 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr @@ -1,16 +1,17 @@ -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/const_eval_limit_reached.rs:17:1 +error: any use of this value will cause an error + --> $DIR/const_eval_limit_reached.rs:8:11 | -LL | / const fn limit() -> usize { -LL | | let x = 42; +LL | / const X: usize = { +LL | | let mut x = 0; +LL | | while x != 1000 { + | | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) LL | | -LL | | x * 42 -LL | | } - | |_^ - -warning: Constant evaluating a complex constant, this might take some time - --> $DIR/const_eval_limit_reached.rs:10:1 +... | +LL | | x +LL | | }; + | |__- | -LL | const CONSTANT: usize = limit(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index 00845a17b116b..e66b432ede20c 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -49,4 +49,36 @@ trait K {} fn foo>(x: X) {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +fn bar(_: F) where F: Fn() -> _ {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +fn baz _>(_: F) {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +struct L(F) where F: Fn() -> _; +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +struct M where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + a: F, +} +enum N where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + Foo(F), +} + +union O where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR unions with non-`Copy` fields are unstable + foo: F, +} + +trait P where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} + +trait Q { + fn foo(_: F) where F: Fn() -> _ {} + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} + fn main() {} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 6d5f3d9f14348..875c02bae4ae0 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -57,6 +57,19 @@ LL | type J = ty!(u8); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0658]: unions with non-`Copy` fields are unstable + --> $DIR/bad-assoc-ty.rs:69:1 + | +LL | / union O where F: Fn() -> _ { +LL | | +LL | | +LL | | foo: F, +LL | | } + | |_^ + | + = note: see issue #55149 for more information + = help: add `#![feature(untagged_unions)]` to the crate attributes to enable + error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 | @@ -129,8 +142,101 @@ LL | fn foo>(x: X) {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo>(x: X) {} + | ^^^ ^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:52:34 + | +LL | fn bar(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn bar(_: F) where F: Fn() -> T {} + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:55:19 + | +LL | fn baz _>(_: F) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn baz T>(_: F) {} + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:58:33 + | +LL | struct L(F) where F: Fn() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct L(F) where F: Fn() -> T; + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:60:30 + | +LL | struct M where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct M where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:64:28 + | +LL | enum N where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | enum N where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:69:29 + | +LL | union O where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | union O where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:75:29 + | +LL | trait P where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | trait P where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:80:38 + | +LL | fn foo(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo(_: F) where F: Fn() -> T {} + | ^^^ ^ -error: aborting due to 20 previous errors +error: aborting due to 29 previous errors -Some errors have detailed explanations: E0121, E0223. +Some errors have detailed explanations: E0121, E0223, E0658. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/generator/borrowing.stderr b/src/test/ui/generator/borrowing.stderr index 83987e19839ce..38e1ace8c4efb 100644 --- a/src/test/ui/generator/borrowing.stderr +++ b/src/test/ui/generator/borrowing.stderr @@ -1,19 +1,16 @@ error[E0597]: `a` does not live long enough --> $DIR/borrowing.rs:9:33 | +LL | let _b = { + | -- borrow later stored here +LL | let a = 3; LL | Pin::new(&mut || yield &a).resume(()) - | ----------^ - | | | - | | borrowed value does not live long enough + | -- ^ borrowed value does not live long enough + | | | value captured here by generator - | a temporary with access to the borrow is created here ... LL | LL | }; - | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator - | | - | `a` dropped here while still borrowed - | - = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block. + | - `a` dropped here while still borrowed error[E0597]: `a` does not live long enough --> $DIR/borrowing.rs:16:20 diff --git a/src/test/ui/generator/retain-resume-ref.stderr b/src/test/ui/generator/retain-resume-ref.stderr index bc715c7030eb3..e33310d12d9ef 100644 --- a/src/test/ui/generator/retain-resume-ref.stderr +++ b/src/test/ui/generator/retain-resume-ref.stderr @@ -4,10 +4,9 @@ error[E0499]: cannot borrow `thing` as mutable more than once at a time LL | gen.as_mut().resume(&mut thing); | ---------- first mutable borrow occurs here LL | gen.as_mut().resume(&mut thing); - | ^^^^^^^^^^ second mutable borrow occurs here -LL | -LL | } - | - first borrow might be used here, when `gen` is dropped and runs the destructor for generator + | ------ ^^^^^^^^^^ second mutable borrow occurs here + | | + | first borrow later used by call error: aborting due to previous error diff --git a/src/test/ui/issues/issue-10656.rs b/src/test/ui/issues/issue-10656.rs index 8918dadb47a35..250c4bc442f98 100644 --- a/src/test/ui/issues/issue-10656.rs +++ b/src/test/ui/issues/issue-10656.rs @@ -1,3 +1,3 @@ #![deny(missing_docs)] #![crate_type="lib"] -//~^^ ERROR missing documentation for crate +//~^^ ERROR missing documentation for the crate diff --git a/src/test/ui/issues/issue-10656.stderr b/src/test/ui/issues/issue-10656.stderr index 2e91a598dce40..2e4365f1ed76b 100644 --- a/src/test/ui/issues/issue-10656.stderr +++ b/src/test/ui/issues/issue-10656.stderr @@ -1,4 +1,4 @@ -error: missing documentation for crate +error: missing documentation for the crate --> $DIR/issue-10656.rs:1:1 | LL | / #![deny(missing_docs)] diff --git a/src/test/ui/lint/lint-missing-doc.rs b/src/test/ui/lint/lint-missing-doc.rs index 77f9a3770a339..bab6f4e9e5e15 100644 --- a/src/test/ui/lint/lint-missing-doc.rs +++ b/src/test/ui/lint/lint-missing-doc.rs @@ -50,8 +50,8 @@ trait B { } pub trait C { //~ ERROR: missing documentation for a trait - fn foo(&self); //~ ERROR: missing documentation for a trait method - fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a trait method + fn foo(&self); //~ ERROR: missing documentation for an associated function + fn foo_with_impl(&self) {} //~ ERROR: missing documentation for an associated function } #[allow(missing_docs)] @@ -78,7 +78,7 @@ impl Foo { } impl PubFoo { - pub fn foo() {} //~ ERROR: missing documentation for a method + pub fn foo() {} //~ ERROR: missing documentation for an associated function /// dox pub fn foo1() {} fn foo2() {} diff --git a/src/test/ui/lint/lint-missing-doc.stderr b/src/test/ui/lint/lint-missing-doc.stderr index a18a97e5f7fb5..21da4fae4c161 100644 --- a/src/test/ui/lint/lint-missing-doc.stderr +++ b/src/test/ui/lint/lint-missing-doc.stderr @@ -40,13 +40,13 @@ error: missing documentation for a trait LL | pub trait C { | ^^^^^^^^^^^ -error: missing documentation for a trait method +error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:53:5 | LL | fn foo(&self); | ^^^^^^^^^^^^^^ -error: missing documentation for a trait method +error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:54:5 | LL | fn foo_with_impl(&self) {} @@ -64,7 +64,7 @@ error: missing documentation for an associated type LL | type AssociatedTypeDef = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing documentation for a method +error: missing documentation for an associated function --> $DIR/lint-missing-doc.rs:81:5 | LL | pub fn foo() {} diff --git a/src/test/ui/lint/lints-in-foreign-macros.rs b/src/test/ui/lint/lints-in-foreign-macros.rs index c96b8f1a5cf4a..1e8b6788a60bb 100644 --- a/src/test/ui/lint/lints-in-foreign-macros.rs +++ b/src/test/ui/lint/lints-in-foreign-macros.rs @@ -1,7 +1,7 @@ // aux-build:lints-in-foreign-macros.rs // check-pass -#![warn(unused_imports)] //~ missing documentation for crate [missing_docs] +#![warn(unused_imports)] //~ missing documentation for the crate [missing_docs] #![warn(missing_docs)] #[macro_use] diff --git a/src/test/ui/lint/lints-in-foreign-macros.stderr b/src/test/ui/lint/lints-in-foreign-macros.stderr index 207d85a89c723..dcea5adb863f6 100644 --- a/src/test/ui/lint/lints-in-foreign-macros.stderr +++ b/src/test/ui/lint/lints-in-foreign-macros.stderr @@ -26,7 +26,7 @@ warning: unused import: `std::string::ToString` LL | mod d { baz2!(use std::string::ToString;); } | ^^^^^^^^^^^^^^^^^^^^^ -warning: missing documentation for crate +warning: missing documentation for the crate --> $DIR/lints-in-foreign-macros.rs:4:1 | LL | / #![warn(unused_imports)] diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index e8aba9d8d4de6..d551ccf9cf669 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -111,7 +111,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-one-region-closure.rs:62:1 diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 58ea527d95980..3e17de1bf0f56 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -93,7 +93,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:52:1 diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 7c82b14739402..e354f1b5f7e63 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -11,7 +11,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] = note: late-bound region is '_#4r = note: number of external vids: 5 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:34:1 @@ -27,13 +27,13 @@ LL | | } | = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> -error[E0309]: the associated type `>::AssocType` may not live long enough +error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 @@ -47,7 +47,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:43:1 @@ -63,13 +63,13 @@ LL | | } | = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> -error[E0309]: the associated type `>::AssocType` may not live long enough +error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 @@ -83,7 +83,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:53:1 @@ -111,7 +111,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 @@ -139,7 +139,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '_#4r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:74:1 @@ -168,7 +168,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] = note: late-bound region is '_#3r = note: number of external vids: 4 - = note: where >::AssocType: '_#2r + = note: where >::AssocType: '_#2r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:83:1 @@ -209,7 +209,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '_#3r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:92:1 @@ -237,7 +237,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); (), ] = note: number of external vids: 3 - = note: where >::AssocType: '_#2r + = note: where >::AssocType: '_#2r note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:101:1 diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs index 5d89d8105b119..b306849ac8e5e 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.rs +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -10,7 +10,7 @@ pub fn leak_dyn_nonprincipal() -> Box { loo #[deny(missing_docs)] fn container() { impl dyn PubPrincipal { - pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + pub fn check_doc_lint() {} //~ ERROR missing documentation for an associated function } impl dyn PubPrincipal + PrivNonPrincipal { pub fn check_doc_lint() {} // OK, no missing doc lint diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr index 2a41fae43c629..778c98671ad4d 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -8,7 +8,7 @@ LL | pub fn leak_dyn_nonprincipal() -> Box = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 -error: missing documentation for a method +error: missing documentation for an associated function --> $DIR/private-in-public-non-principal.rs:13:9 | LL | pub fn check_doc_lint() {} diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 6cd2b8c75b639..5444fc62d8211 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -158,12 +158,9 @@ trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -178,14 +175,12 @@ struct BadStruct2<_, T>(_, T); type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index dc86ab30dfe41..955765e1175ce 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -11,25 +11,25 @@ LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:170:19 + --> $DIR/typeck_type_placeholder_item.rs:167:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:170:22 + --> $DIR/typeck_type_placeholder_item.rs:167:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:175:19 + --> $DIR/typeck_type_placeholder_item.rs:172:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:208:5 + --> $DIR/typeck_type_placeholder_item.rs:203:5 | LL | const C: _; | ^^^^^^^^^^- @@ -37,7 +37,7 @@ LL | const C: _; | help: provide a definition for the constant: `= ;` error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:170:22 + --> $DIR/typeck_type_placeholder_item.rs:167:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -351,18 +351,6 @@ help: use type parameters instead LL | struct BadStruct(T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:32 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:15 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:159:15 | @@ -377,13 +365,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:34 + --> $DIR/typeck_type_placeholder_item.rs:162:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:25 + --> $DIR/typeck_type_placeholder_item.rs:167:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -394,7 +382,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:25 + --> $DIR/typeck_type_placeholder_item.rs:172:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -405,13 +393,7 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:14 - | -LL | type X = Box<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:14 + --> $DIR/typeck_type_placeholder_item.rs:176:14 | LL | type X = Box<_>; | ^ not allowed in type signatures @@ -531,37 +513,25 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:34 - | -LL | fn impl_trait() -> impl BadTrait<_> { - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 - | -LL | type Y = impl Trait<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 + --> $DIR/typeck_type_placeholder_item.rs:182:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:195:14 + --> $DIR/typeck_type_placeholder_item.rs:190:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:197:14 + --> $DIR/typeck_type_placeholder_item.rs:192:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:199:14 + --> $DIR/typeck_type_placeholder_item.rs:194:14 | LL | const D: _ = 42; | ^ @@ -606,25 +576,25 @@ LL | fn clone(&self) -> _ { FnTest9 } | help: replace with the correct return type: `main::FnTest9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:204:14 + --> $DIR/typeck_type_placeholder_item.rs:199:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:206:14 + --> $DIR/typeck_type_placeholder_item.rs:201:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:208:14 + --> $DIR/typeck_type_placeholder_item.rs:203:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:211:14 + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | const D: _ = 42; | ^ @@ -632,7 +602,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace `_` with the correct type: `i32` -error: aborting due to 71 previous errors +error: aborting due to 66 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`.