From 2daaf2b252040ff542eb42d66043f62c360c4db5 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 15 Mar 2020 21:48:09 -0500 Subject: [PATCH 01/30] replace some adhoc logic with article_and_descr --- src/librustc_lint/builtin.rs | 45 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 88f2284cd6154..14ad35767b992 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -349,7 +349,7 @@ impl MissingDoc { id: Option, attrs: &[ast::Attribute], sp: Span, - desc: &'static str, + desc: &str, ) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. @@ -413,12 +413,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 +423,45 @@ 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, + &format!("{} {}", article, desc), + ); } fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, trait_item: &hir::TraitItem<'_>) { From 1661a0a99ba09ff0b2cce8ad99c4f18150165b80 Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 21 Mar 2020 19:47:23 -0500 Subject: [PATCH 02/30] convert a couple more errors --- src/librustc_lint/builtin.rs | 19 ++++++------------- src/test/ui/lint/lint-missing-doc.rs | 6 +++--- src/test/ui/lint/lint-missing-doc.stderr | 6 +++--- .../private-in-public-non-principal.rs | 2 +- .../private-in-public-non-principal.stderr | 2 +- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 14ad35767b992..9a02bebb2355f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -469,18 +469,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, - desc, + &format!("{} {}", article, desc), ); } @@ -490,18 +487,14 @@ 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, - desc, + &format!("{} {}", article, desc), ); } 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/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() {} From cdb2c3c36819870e155f4711e67e8b417356c8a4 Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 21 Mar 2020 21:32:35 -0500 Subject: [PATCH 03/30] use static strs --- src/librustc_lint/builtin.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9a02bebb2355f..24529db48aa2b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -349,7 +349,8 @@ impl MissingDoc { id: Option, attrs: &[ast::Attribute], sp: Span, - desc: &str, + article: &'static str, + desc: &'static str, ) { // If we're building a test harness, then warning about // documentation is probably not really relevant right now. @@ -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, "a", "crate"); for macro_def in krate.exported_macros { let has_doc = macro_def.attrs.iter().any(|a| has_doc(a)); @@ -455,13 +456,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { 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, - &format!("{} {}", article, desc), - ); + 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<'_>) { @@ -477,7 +472,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { Some(trait_item.hir_id), &trait_item.attrs, trait_item.span, - &format!("{} {}", article, desc), + article, + desc, ); } @@ -494,18 +490,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { Some(impl_item.hir_id), &impl_item.attrs, impl_item.span, - &format!("{} {}", article, desc), + 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"); } } From 1e5d81de1d8485e9ce2995bc6b1559f25c4d86e5 Mon Sep 17 00:00:00 2001 From: Wonwoo Choi Date: Sun, 22 Mar 2020 18:02:18 +0900 Subject: [PATCH 04/30] Fix invalid suggestion on `&mut` iterators yielding `&` references --- .../diagnostics/mutability_errors.rs | 82 +++++++++++++------ .../issue-69789-iterator-mut-suggestion.rs | 11 +++ ...issue-69789-iterator-mut-suggestion.stderr | 12 +++ 3 files changed, 82 insertions(+), 23 deletions(-) create mode 100644 src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.rs create mode 100644 src/test/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr 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/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`. From 82f4a1a9b98ef7f16b25de44150d004c3b1b528a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 22 Mar 2020 11:41:07 +0100 Subject: [PATCH 05/30] get rid of ConstPropUnsupported; use ZST marker structs instead --- src/libcore/any.rs | 2 +- src/librustc/mir/interpret/error.rs | 49 ++++++++++++++++++------ src/librustc/mir/interpret/mod.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 32 +++++++++++----- 4 files changed, 63 insertions(+), 24 deletions(-) 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/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index ff107a5f1e268..fd7f5361214f4 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -14,7 +14,10 @@ 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, TypeId}, + fmt, mem, +}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { @@ -451,9 +454,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. @@ -472,9 +472,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) } @@ -516,6 +513,35 @@ impl fmt::Debug for ResourceExhaustionInfo { } } +/// A trait for machine-specific errors (or other "machine stop" conditions). +pub trait MachineStopType: Any + fmt::Debug + Send {} +impl MachineStopType for String {} + +// Copy-pasted from `any.rs`; there does not seem to be a way to re-use that. +impl dyn MachineStopType { + pub fn is(&self) -> bool { + // Get `TypeId` of the type this function is instantiated with. + let t = TypeId::of::(); + + // Get `TypeId` of the type in the trait object (`self`). + let concrete = self.type_id(); + + // Compare both `TypeId`s on equality. + t == concrete + } + + pub fn downcast_ref(&self) -> Option<&T> { + if self.is::() { + // SAFETY: just checked whether we are pointing to the correct type, and we can rely on + // that check for memory safety because `Any` is implemented for all types; no other + // impls can exist as they would conflict with our impl. + unsafe { Some(&*(self as *const dyn MachineStopType as *const T)) } + } else { + None + } + } +} + pub enum InterpError<'tcx> { /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo), @@ -529,7 +555,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>; @@ -549,7 +575,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), } } } @@ -560,8 +586,9 @@ impl InterpError<'_> { /// waste of resources. pub fn allocates(&self) -> bool { match self { - InterpError::MachineStop(_) - | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) + // Zero-sized boxes to not allocate. + InterpError::MachineStop(b) => mem::size_of_val(&**b) > 0, + InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true, diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index dfe5adb1bbff0..35876c8e95ab5 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -92,8 +92,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/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 8d7cafc34b356..687bacfdc1b83 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpResult, Scalar}; +use rustc::mir::interpret::{InterpResult, MachineStopType, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; @@ -192,7 +192,10 @@ 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")) + #[derive(Debug)] + struct ConstPropIntrinsic; + impl MachineStopType for ConstPropIntrinsic {} + throw_machine_stop!(ConstPropIntrinsic) } fn assert_panic( @@ -204,7 +207,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( @@ -213,11 +216,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + #[derive(Debug)] + struct ConstPropPtrOp; + impl MachineStopType for ConstPropPtrOp {} // 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!(ConstPropPtrOp) } #[inline(always)] @@ -240,7 +243,10 @@ 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")) + #[derive(Debug)] + struct ConstPropBox; + impl MachineStopType for ConstPropBox {} + throw_machine_stop!(ConstPropBox) } fn access_local( @@ -251,7 +257,10 @@ 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")); + #[derive(Debug)] + struct ConstPropUninitLocal; + impl MachineStopType for ConstPropUninitLocal {} + throw_machine_stop!(ConstPropUninitLocal) } l.access() @@ -261,10 +270,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _memory_extra: &(), allocation: &Allocation, ) -> InterpResult<'tcx> { + #[derive(Debug)] + struct ConstPropGlobalMem; + impl MachineStopType for ConstPropGlobalMem {} // 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!(ConstPropGlobalMem) } Ok(()) From 12607ef569dfa086d5475d0d7b1858965931519b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Dec 2019 20:12:49 +0100 Subject: [PATCH 06/30] Add lint when no doc is present at the crate-level --- src/librustc_session/lint/builtin.rs | 7 +++++++ src/librustdoc/core.rs | 19 +++++++++++++++++++ .../rustdoc-ui/no-crate-level-doc-lint.rs | 3 +++ .../rustdoc-ui/no-crate-level-doc-lint.stderr | 13 +++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 src/test/rustdoc-ui/no-crate-level-doc-lint.rs create mode 100644 src/test/rustdoc-ui/no-crate-level-doc-lint.stderr diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index f8a4e024605aa..deb119ccb9730 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 NO_CRATE_LEVEL_DOC, + 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, + NO_CRATE_LEVEL_DOC, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, WHERE_CLAUSES_OBJECT_SAFETY, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index f0b9ad2852f51..a45761ba4a8b2 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_doc = rustc_lint::builtin::NO_CRATE_LEVEL_DOC.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_doc.to_owned(), ]; whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); @@ -411,6 +413,23 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut krate = clean::krate(&mut ctxt); + if let Some(ref m) = krate.module { + match m.doc_value() { + None | Some("") => { + let mut diag = tcx.struct_lint_node( + rustc_lint::builtin::NO_CRATE_LEVEL_DOC, + ctxt.as_local_hir_id(m.def_id).unwrap(), + "No documentation found on this crate top module.\n\n\ + Maybe you could be interested into looking at this documentation:\n\ + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ + .html" + ); + diag.emit(); + } + _ => {} + } + } + fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) { let mut msg = diag.struct_warn(&format!( "the `#![doc({})]` attribute is \ 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..e939f3a44d3ff --- /dev/null +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs @@ -0,0 +1,3 @@ +#![deny(no_crate_level_doc)] + +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..45c2493686883 --- /dev/null +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr @@ -0,0 +1,13 @@ +error: No documentation found on this crate top module. + +Maybe you could be interested into looking at this documentation: +https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html + | +note: lint level defined here + --> $DIR/no-crate-level-doc-lint.rs:1:9 + | +LL | #![deny(no_crate_level_doc)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From f767f541e7a7eed4cd827511146372021acacc22 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 11 Feb 2020 11:45:40 +0100 Subject: [PATCH 07/30] rename NO_CRATE_LEVEL_DOC lint into MISSING_CRATE_LEVEL_DOC --- src/librustc_session/lint/builtin.rs | 4 ++-- src/librustdoc/core.rs | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index deb119ccb9730..1c010139ef6db 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -387,7 +387,7 @@ declare_lint! { } declare_lint! { - pub NO_CRATE_LEVEL_DOC, + pub MISSING_CRATE_LEVEL_DOC, Allow, "detects crates with no crate-level documentation" } @@ -553,7 +553,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, INTRA_DOC_LINK_RESOLUTION_FAILURE, - NO_CRATE_LEVEL_DOC, + MISSING_CRATE_LEVEL_DOC, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, WHERE_CLAUSES_OBJECT_SAFETY, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a45761ba4a8b2..47b6699368ccf 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -249,7 +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_doc = rustc_lint::builtin::NO_CRATE_LEVEL_DOC.name; + let no_crate_level_doc = rustc_lint::builtin::MISSING_CRATE_LEVEL_DOC.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. @@ -417,7 +417,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt match m.doc_value() { None | Some("") => { let mut diag = tcx.struct_lint_node( - rustc_lint::builtin::NO_CRATE_LEVEL_DOC, + rustc_lint::builtin::MISSING_CRATE_LEVEL_DOC, ctxt.as_local_hir_id(m.def_id).unwrap(), "No documentation found on this crate top module.\n\n\ Maybe you could be interested into looking at this documentation:\n\ @@ -432,8 +432,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt 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( From a8b0e404875c1e08b330ddea1a2b9a520c193097 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 11 Feb 2020 13:16:38 +0100 Subject: [PATCH 08/30] Improve code readability --- src/librustdoc/core.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 47b6699368ccf..116bb70dcf62f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -414,19 +414,18 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut krate = clean::krate(&mut ctxt); if let Some(ref m) = krate.module { - match m.doc_value() { - None | Some("") => { - let mut diag = tcx.struct_lint_node( - rustc_lint::builtin::MISSING_CRATE_LEVEL_DOC, - ctxt.as_local_hir_id(m.def_id).unwrap(), - "No documentation found on this crate top module.\n\n\ - Maybe you could be interested into looking at this documentation:\n\ - https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ - .html" - ); - diag.emit(); - } - _ => {} + if let None | Some("") = m.doc_value() { + let mut diag = tcx.struct_lint_node( + rustc_lint::builtin::MISSING_CRATE_LEVEL_DOC, + ctxt.as_local_hir_id(m.def_id).unwrap(), + "no documentation found for this crate's top-level module", + ); + diag.help( + "The following guide may be of use:\n\ + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ + .html", + ); + diag.emit(); } } From ffe1289fd249d31cd98b2da168281ba860330987 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 11 Feb 2020 13:16:46 +0100 Subject: [PATCH 09/30] Update tests --- src/test/rustdoc-ui/no-crate-level-doc-lint.rs | 2 +- src/test/rustdoc-ui/no-crate-level-doc-lint.stderr | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs index e939f3a44d3ff..c65af73ead1e5 100644 --- a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs @@ -1,3 +1,3 @@ -#![deny(no_crate_level_doc)] +#![deny(missing_crate_level_doc)] 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 index 45c2493686883..f8d3723e7b0b4 100644 --- a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr @@ -1,13 +1,12 @@ -error: No documentation found on this crate top module. - -Maybe you could be interested into looking at this documentation: -https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html +error: no documentation found for this crate's top-level module | -note: lint level defined here +note: the lint level is defined here --> $DIR/no-crate-level-doc-lint.rs:1:9 | -LL | #![deny(no_crate_level_doc)] - | ^^^^^^^^^^^^^^^^^^ +LL | #![deny(missing_crate_level_doc)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = 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 From 966400253b3c5df2ed96e443d64147244dc6f338 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Feb 2020 15:48:08 +0100 Subject: [PATCH 10/30] Update to new diagnostic --- src/librustdoc/core.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 116bb70dcf62f..4d2d81e48fc9e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -415,17 +415,20 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt if let Some(ref m) = krate.module { if let None | Some("") = m.doc_value() { - let mut diag = tcx.struct_lint_node( + 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_DOC, ctxt.as_local_hir_id(m.def_id).unwrap(), - "no documentation found for this crate's top-level module", - ); - diag.help( - "The following guide may be of use:\n\ - https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ - .html", + |lint| { + let mut diag = lint.build( + "no documentation found for this crate's top-level module", + ); + diag.help(help); + diag.emit(); + }, ); - diag.emit(); } } From be97eb4ece63b9e8e094939eb724885fcc2a6919 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 22 Mar 2020 13:04:23 +0100 Subject: [PATCH 11/30] Update lint name to follow convention --- src/librustc_session/lint/builtin.rs | 4 ++-- src/librustdoc/core.rs | 6 +++--- src/test/rustdoc-ui/no-crate-level-doc-lint.rs | 2 +- src/test/rustdoc-ui/no-crate-level-doc-lint.stderr | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 1c010139ef6db..9ad6e792c28ba 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -387,7 +387,7 @@ declare_lint! { } declare_lint! { - pub MISSING_CRATE_LEVEL_DOC, + pub MISSING_CRATE_LEVEL_DOCS, Allow, "detects crates with no crate-level documentation" } @@ -553,7 +553,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, INTRA_DOC_LINK_RESOLUTION_FAILURE, - MISSING_CRATE_LEVEL_DOC, + MISSING_CRATE_LEVEL_DOCS, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, WHERE_CLAUSES_OBJECT_SAFETY, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 4d2d81e48fc9e..fe3a9b6b3dcdd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -249,7 +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_doc = rustc_lint::builtin::MISSING_CRATE_LEVEL_DOC.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. @@ -259,7 +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_doc.to_owned(), + no_crate_level_docs.to_owned(), ]; whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); @@ -419,7 +419,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ .html"; tcx.struct_lint_node( - rustc_lint::builtin::MISSING_CRATE_LEVEL_DOC, + rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS, ctxt.as_local_hir_id(m.def_id).unwrap(), |lint| { let mut diag = lint.build( diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs index c65af73ead1e5..152a7cd88bcb1 100644 --- a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs @@ -1,3 +1,3 @@ -#![deny(missing_crate_level_doc)] +#![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 index f8d3723e7b0b4..6e7e2fb3eb73f 100644 --- a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr @@ -3,8 +3,8 @@ 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_doc)] - | ^^^^^^^^^^^^^^^^^^^^^^^ +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 From d40dff9cbbabfdb1477dfbb71f45ca4f36c1d596 Mon Sep 17 00:00:00 2001 From: mark Date: Sun, 22 Mar 2020 14:37:51 -0500 Subject: [PATCH 12/30] the crate and tests --- src/librustc_lint/builtin.rs | 2 +- src/test/ui/issues/issue-10656.rs | 2 +- src/test/ui/issues/issue-10656.stderr | 2 +- src/test/ui/lint/lints-in-foreign-macros.rs | 2 +- src/test/ui/lint/lints-in-foreign-macros.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 24529db48aa2b..66d9fe7e14988 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -399,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, "a", "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)); 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/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)] From cda81da6ea4c037ef036067d9cb98e80208ee525 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 22 Mar 2020 20:24:22 +0100 Subject: [PATCH 13/30] avoid unsafe code, use upcasting-trait instead (trick by oli) --- src/librustc/mir/interpret/error.rs | 41 +++++++++++------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index fd7f5361214f4..d00eb7921a04b 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -14,10 +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, TypeId}, - fmt, mem, -}; +use std::{any::Any, fmt, mem}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { @@ -513,32 +510,26 @@ impl fmt::Debug for ResourceExhaustionInfo { } } +/// 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: Any + fmt::Debug + Send {} +pub trait MachineStopType: AsAny + fmt::Debug + Send {} impl MachineStopType for String {} -// Copy-pasted from `any.rs`; there does not seem to be a way to re-use that. impl dyn MachineStopType { - pub fn is(&self) -> bool { - // Get `TypeId` of the type this function is instantiated with. - let t = TypeId::of::(); - - // Get `TypeId` of the type in the trait object (`self`). - let concrete = self.type_id(); - - // Compare both `TypeId`s on equality. - t == concrete - } - + #[inline(always)] pub fn downcast_ref(&self) -> Option<&T> { - if self.is::() { - // SAFETY: just checked whether we are pointing to the correct type, and we can rely on - // that check for memory safety because `Any` is implemented for all types; no other - // impls can exist as they would conflict with our impl. - unsafe { Some(&*(self as *const dyn MachineStopType as *const T)) } - } else { - None - } + self.as_any().downcast_ref() } } From 5e8b795552fed746ec1bbd1d397d7fb11a0faacd Mon Sep 17 00:00:00 2001 From: mark Date: Sun, 22 Mar 2020 17:18:30 -0500 Subject: [PATCH 14/30] fix one more test --- src/test/rustdoc-ui/deny-missing-docs-crate.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)] From 410385dfd0532f3e8867afaaa4b89c315b0e84b1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Mar 2020 10:58:43 +0100 Subject: [PATCH 15/30] add macro to reduce boilerplate and keep readable messages --- src/librustc/mir/interpret/error.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 45 +++++++++++++----------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index d00eb7921a04b..010b73db9ac20 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -577,7 +577,7 @@ impl InterpError<'_> { /// waste of resources. pub fn allocates(&self) -> bool { match self { - // Zero-sized boxes to not allocate. + // Zero-sized boxes do not allocate. InterpError::MachineStop(b) => mem::size_of_val(&**b) > 0, InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 687bacfdc1b83..74140a1fc6daf 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpResult, MachineStopType, Scalar}; +use rustc::mir::interpret::{InterpResult, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; @@ -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,10 +210,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _ret: Option<(PlaceTy<'tcx>, BasicBlock)>, _unwind: Option, ) -> InterpResult<'tcx> { - #[derive(Debug)] - struct ConstPropIntrinsic; - impl MachineStopType for ConstPropIntrinsic {} - throw_machine_stop!(ConstPropIntrinsic) + throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp") } fn assert_panic( @@ -216,11 +231,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { - #[derive(Debug)] - struct ConstPropPtrOp; - impl MachineStopType for ConstPropPtrOp {} // We can't do this because aliasing of memory can differ between const eval and llvm - throw_machine_stop!(ConstPropPtrOp) + throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } #[inline(always)] @@ -243,10 +255,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - #[derive(Debug)] - struct ConstPropBox; - impl MachineStopType for ConstPropBox {} - throw_machine_stop!(ConstPropBox) + throw_machine_stop_str!("can't const prop heap allocations") } fn access_local( @@ -257,10 +266,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { let l = &frame.locals[local]; if l.value == LocalValue::Uninitialized { - #[derive(Debug)] - struct ConstPropUninitLocal; - impl MachineStopType for ConstPropUninitLocal {} - throw_machine_stop!(ConstPropUninitLocal) + throw_machine_stop_str!("tried to access an uninitialized local") } l.access() @@ -270,13 +276,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { _memory_extra: &(), allocation: &Allocation, ) -> InterpResult<'tcx> { - #[derive(Debug)] - struct ConstPropGlobalMem; - impl MachineStopType for ConstPropGlobalMem {} // 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_machine_stop!(ConstPropGlobalMem) + throw_machine_stop_str!("can't eval mutable statics in ConstProp") } Ok(()) From e619b85776feca7ae484c42dff1e37e0844aa06c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Mar 2020 11:03:39 +0100 Subject: [PATCH 16/30] make sure we are checking the size of the right thing --- src/librustc/mir/interpret/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 010b73db9ac20..bd7d2c57509b3 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -578,7 +578,7 @@ impl InterpError<'_> { pub fn allocates(&self) -> bool { match self { // Zero-sized boxes do not allocate. - InterpError::MachineStop(b) => mem::size_of_val(&**b) > 0, + InterpError::MachineStop(b) => mem::size_of_val::(&**b) > 0, InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) From 19e69359564c919023e294b485d952bc240260e2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 23 Mar 2020 12:40:14 +0100 Subject: [PATCH 17/30] Clean up E0452 explanation --- src/librustc_error_codes/error_codes/E0452.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From 799b15ed96942aec81aecab4b2ae2f9243b632fa Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 14 Mar 2020 15:30:35 +0100 Subject: [PATCH 18/30] Evaluate repeat expression lengths as late as possible --- src/librustc/mir/mod.rs | 32 +++++--- src/librustc/mir/tcx.rs | 4 +- src/librustc/ty/sty.rs | 70 ++++++++++++++++- src/librustc_codegen_ssa/mir/rvalue.rs | 3 + .../borrow_check/type_check/mod.rs | 6 +- src/librustc_mir_build/hair/cx/expr.rs | 31 +------- src/librustc_mir_build/hair/mod.rs | 2 +- src/librustc_typeck/astconv.rs | 77 +------------------ src/librustc_typeck/check/expr.rs | 21 +---- src/librustc_typeck/check/mod.rs | 7 +- src/test/compile-fail/issue-52443.rs | 7 +- src/test/ui/closures/issue-52437.rs | 1 + src/test/ui/closures/issue-52437.stderr | 12 ++- .../ui/const-generics/issues/issue-61336-1.rs | 3 +- .../issues/issue-61336-1.stderr | 8 -- .../ui/const-generics/issues/issue-61336-2.rs | 7 +- .../issues/issue-61336-2.stderr | 22 +++--- .../ui/const-generics/issues/issue-61336.rs | 3 +- .../const-generics/issues/issue-61336.stderr | 20 ++--- .../ui/const-generics/issues/issue-62456.rs | 3 +- .../const-generics/issues/issue-62456.stderr | 8 -- .../ui/const-generics/issues/issue-62504.rs | 2 +- .../const-generics/issues/issue-62504.stderr | 10 ++- .../ui/const-generics/issues/issue-67739.rs | 3 +- .../const-generics/issues/issue-67739.stderr | 8 -- .../const-eval/const-eval-overflow-3.rs | 1 + .../const-eval/const-eval-overflow-3.stderr | 14 +++- .../const-eval/const-eval-overflow-3b.rs | 1 + .../const-eval/const-eval-overflow-3b.stderr | 11 ++- src/test/ui/consts/const-eval/issue-52442.rs | 4 +- .../ui/consts/const-eval/issue-52442.stderr | 20 +---- .../consts/const-eval/match-test-ptr-null.rs | 2 +- .../const-eval/match-test-ptr-null.stderr | 27 ++++++- src/test/ui/consts/issue-52432.rs | 1 - src/test/ui/consts/issue-52432.stderr | 12 +-- src/test/ui/consts/too_generic_eval_ice.rs | 1 + .../ui/consts/too_generic_eval_ice.stderr | 12 ++- src/test/ui/issues/issue-39559-2.rs | 1 + src/test/ui/issues/issue-39559-2.stderr | 16 +++- src/test/ui/issues/issue-52060.rs | 1 + src/test/ui/issues/issue-52060.stderr | 13 +++- ...issue-69602-type-err-during-codegen-ice.rs | 1 - ...e-69602-type-err-during-codegen-ice.stderr | 8 +- src/test/ui/repeat_count.stderr | 12 +-- ...issue-65035-static-with-parent-generics.rs | 1 + ...e-65035-static-with-parent-generics.stderr | 14 +++- 46 files changed, 279 insertions(+), 264 deletions(-) delete mode 100644 src/test/ui/const-generics/issues/issue-67739.stderr diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9018cd2656f9f..d81b940cbe797 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2066,7 +2066,7 @@ pub enum Rvalue<'tcx> { Use(Operand<'tcx>), /// [x; 32] - Repeat(Operand<'tcx>, u64), + Repeat(Operand<'tcx>, &'tcx ty::Const<'tcx>), /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), @@ -2194,7 +2194,11 @@ impl<'tcx> Debug for Rvalue<'tcx> { match *self { Use(ref place) => write!(fmt, "{:?}", place), - Repeat(ref a, ref b) => write!(fmt, "[{:?}; {:?}]", a, b), + Repeat(ref a, ref b) => { + write!(fmt, "[{:?}; ", a)?; + pretty_print_const(b, fmt, false)?; + write!(fmt, "]") + } Len(ref a) => write!(fmt, "Len({:?})", a), Cast(ref kind, ref place, ref ty) => { write!(fmt, "{:?} as {:?} ({:?})", place, ty, kind) @@ -2562,18 +2566,26 @@ impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - use crate::ty::print::PrettyPrinter; write!(fmt, "const ")?; - ty::tls::with(|tcx| { - let literal = tcx.lift(&self.literal).unwrap(); - let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS); - cx.print_alloc_ids = true; - cx.pretty_print_const(literal, true)?; - Ok(()) - }) + pretty_print_const(self.literal, fmt, true) } } +fn pretty_print_const( + c: &ty::Const<'tcx>, + fmt: &mut Formatter<'_>, + print_types: bool, +) -> fmt::Result { + use crate::ty::print::PrettyPrinter; + ty::tls::with(|tcx| { + let literal = tcx.lift(&c).unwrap(); + let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS); + cx.print_alloc_ids = true; + cx.pretty_print_const(literal, print_types)?; + Ok(()) + }) +} + impl<'tcx> graph::DirectedGraph for Body<'tcx> { type Node = BasicBlock; } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 13996a74acb35..feb6631926712 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -149,7 +149,9 @@ impl<'tcx> Rvalue<'tcx> { { match *self { Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), - Rvalue::Repeat(ref operand, count) => tcx.mk_array(operand.ty(local_decls, tcx), count), + Rvalue::Repeat(ref operand, count) => { + tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count)) + } Rvalue::Ref(reg, bk, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 00310ef9b3127..5d1f6ae387740 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -8,7 +8,7 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; use crate::middle::region; use crate::mir::interpret::ConstValue; -use crate::mir::interpret::Scalar; +use crate::mir::interpret::{LitToConstInput, Scalar}; use crate::mir::Promoted; use crate::ty::layout::VariantIdx; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; @@ -2401,7 +2401,75 @@ pub struct Const<'tcx> { #[cfg(target_arch = "x86_64")] static_assert_size!(Const<'_>, 48); +/// Returns the `DefId` of the constant parameter that the provided expression is a path to. +fn const_param_def_id(expr: &hir::Expr<'_>) -> Option { + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, + }; + + match &expr.kind { + hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res { + hir::def::Res::Def(hir::def::DefKind::ConstParam, did) => Some(did), + _ => None, + }, + _ => None, + } +} + impl<'tcx> Const<'tcx> { + pub fn from_hir_anon_const( + tcx: TyCtxt<'tcx>, + ast_const: &hir::AnonConst, + ty: Ty<'tcx>, + ) -> &'tcx Self { + debug!("Const::from_hir_anon_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const); + + let def_id = tcx.hir().local_def_id(ast_const.hir_id); + + let expr = &tcx.hir().body(ast_const.body).value; + + let lit_input = match expr.kind { + hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind { + hir::ExprKind::Lit(ref lit) => { + Some(LitToConstInput { lit: &lit.node, ty, neg: true }) + } + _ => None, + }, + _ => None, + }; + + if let Some(lit_input) = lit_input { + // If an error occurred, ignore that it's a literal and leave reporting the error up to + // mir. + if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { + return c; + } else { + tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const"); + } + } + + let kind = if let Some(def_id) = const_param_def_id(expr) { + // Find the name and index of the const parameter by indexing the generics of the + // parent item and construct a `ParamConst`. + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + let item_id = tcx.hir().get_parent_node(hir_id); + let item_def_id = tcx.hir().local_def_id(item_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; + let name = tcx.hir().name(hir_id); + ty::ConstKind::Param(ty::ParamConst::new(index, name)) + } else { + ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id), None) + }; + tcx.mk_const(ty::Const { val: kind, ty }) + } + #[inline] pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { val: ConstKind::Value(val), ty }) diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 245df0846b583..880bce7fde487 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -106,6 +106,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + let count = + self.monomorphize(&count).eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); + bx.write_operand_repeatedly(cg_elem, count, dest) } diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 521861624cb7a..e1aacb1fa2637 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1986,7 +1986,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } Rvalue::Repeat(operand, len) => { - if *len > 1 { + // If the length cannot be evaluated we must assume that the length can be larger + // than 1. + // If the length is larger than 1, the repeat expression will need to copy the + // element, so we require the `Copy` trait. + if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) { if let Operand::Move(_) = operand { // While this is located in `nll::typeck` this error is not an NLL error, it's // a required check to make sure that repeated elements implement `Copy`. diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 02b596863ab40..b9c9e9834eff8 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -3,7 +3,7 @@ use crate::hair::cx::to_ref::ToRef; use crate::hair::cx::Cx; use crate::hair::util::UserAnnotatedTyHelpers; use crate::hair::*; -use rustc::mir::interpret::{ErrorHandled, Scalar}; +use rustc::mir::interpret::Scalar; use rustc::mir::BorrowKind; use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; @@ -406,34 +406,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { - let def_id = cx.tcx.hir().local_def_id(count.hir_id); - let substs = InternalSubsts::identity_for_item(cx.tcx, def_id); - let span = cx.tcx.def_span(def_id); - let count = match cx.tcx.const_eval_resolve( - ty::ParamEnv::reveal_all(), - def_id, - substs, - None, - Some(span), - ) { - Ok(cv) => { - if let Some(count) = cv.try_to_bits_for_ty( - cx.tcx, - ty::ParamEnv::reveal_all(), - cx.tcx.types.usize, - ) { - count as u64 - } else { - bug!("repeat count constant value can't be converted to usize"); - } - } - Err(ErrorHandled::Reported) => 0, - Err(ErrorHandled::TooGeneric) => { - let span = cx.tcx.def_span(def_id); - cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters"); - 0 - } - }; + let count = ty::Const::from_hir_anon_const(cx.tcx, count, cx.tcx.types.usize); ExprKind::Repeat { value: v.to_ref(), count } } diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs index cb93ba7c9250f..77042240acf32 100644 --- a/src/librustc_mir_build/hair/mod.rs +++ b/src/librustc_mir_build/hair/mod.rs @@ -229,7 +229,7 @@ crate enum ExprKind<'tcx> { }, Repeat { value: ExprRef<'tcx>, - count: u64, + count: &'tcx Const<'tcx>, }, Array { fields: Vec>, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 408e5c2d2f24d..2d7bf81aedd6d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -22,7 +22,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::print; -use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; +use rustc_hir::{Constness, GenericArg, GenericArgs}; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; use rustc_session::parse::feature_err; use rustc_session::Session; @@ -39,8 +39,6 @@ use std::collections::BTreeSet; use std::iter; use std::slice; -use rustc::mir::interpret::LitToConstInput; - #[derive(Debug)] pub struct PathSeg(pub DefId, pub usize); @@ -782,7 +780,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into() + ty::Const::from_hir_anon_const(tcx, &ct.value, tcx.type_of(param.def_id)).into() } _ => unreachable!(), }, @@ -2766,7 +2764,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .unwrap_or(tcx.types.err) } hir::TyKind::Array(ref ty, ref length) => { - let length = self.ast_const_to_const(length, tcx.types.usize); + let length = ty::Const::from_hir_anon_const(tcx, length, tcx.types.usize); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } @@ -2798,75 +2796,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { result_ty } - /// Returns the `DefId` of the constant parameter that the provided expression is a path to. - pub fn const_param_def_id(&self, expr: &hir::Expr<'_>) -> Option { - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - - match &expr.kind { - ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res { - Res::Def(DefKind::ConstParam, did) => Some(did), - _ => None, - }, - _ => None, - } - } - - pub fn ast_const_to_const( - &self, - ast_const: &hir::AnonConst, - ty: Ty<'tcx>, - ) -> &'tcx ty::Const<'tcx> { - debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const); - - let tcx = self.tcx(); - let def_id = tcx.hir().local_def_id(ast_const.hir_id); - - let expr = &tcx.hir().body(ast_const.body).value; - - let lit_input = match expr.kind { - hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind { - hir::ExprKind::Lit(ref lit) => { - Some(LitToConstInput { lit: &lit.node, ty, neg: true }) - } - _ => None, - }, - _ => None, - }; - - if let Some(lit_input) = lit_input { - // If an error occurred, ignore that it's a literal and leave reporting the error up to - // mir. - if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { - return c; - } else { - tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const"); - } - } - - let kind = if let Some(def_id) = self.const_param_def_id(expr) { - // Find the name and index of the const parameter by indexing the generics of the - // parent item and construct a `ParamConst`. - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let item_id = tcx.hir().get_parent_node(hir_id); - let item_def_id = tcx.hir().local_def_id(item_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; - let name = tcx.hir().name(hir_id); - ty::ConstKind::Param(ty::ParamConst::new(index, name)) - } else { - ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id), None) - }; - tcx.mk_const(ty::Const { val: kind, ty }) - } - pub fn impl_trait_ty_to_ty( &self, def_id: DefId, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 7203980b2388f..e57e6cd80ca14 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -18,7 +18,6 @@ use crate::type_error_struct; use crate::util::common::ErrorReported; use rustc::middle::lang_items; -use rustc::mir::interpret::ErrorHandled; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::Ty; @@ -1009,12 +1008,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let count_def_id = tcx.hir().local_def_id(count.hir_id); - let count = if self.const_param_def_id(count).is_some() { - Ok(self.to_const(count, tcx.type_of(count_def_id))) - } else { - tcx.const_eval_poly(count_def_id) - .map(|val| ty::Const::from_value(tcx, val, tcx.type_of(count_def_id))) - }; + let count = self.to_const(count, tcx.type_of(count_def_id)); let uty = match expected { ExpectHasType(uty) => match uty.kind { @@ -1042,17 +1036,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if element_ty.references_error() { return tcx.types.err; } - match count { - Ok(count) => tcx.mk_ty(ty::Array(t, count)), - Err(ErrorHandled::TooGeneric) => { - self.tcx.sess.span_err( - tcx.def_span(count_def_id), - "array lengths can't depend on generic parameters", - ); - tcx.types.err - } - Err(ErrorHandled::Reported) => tcx.types.err, - } + + tcx.mk_ty(ty::Array(t, count)) } fn check_expr_tuple( diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 32f0f578d057f..292ad1e94a72e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3279,13 +3279,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } - /// Returns the `DefId` of the constant parameter that the provided expression is a path to. - pub fn const_param_def_id(&self, hir_c: &hir::AnonConst) -> Option { - AstConv::const_param_def_id(self, &self.tcx.hir().body(hir_c.body).value) - } - pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - AstConv::ast_const_to_const(self, ast_c, ty) + ty::Const::from_hir_anon_const(self.tcx, ast_c, ty) } // If the type given by the user has free regions, save it for later, since diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs index 597fbbf00d53c..3a022230b39a7 100644 --- a/src/test/compile-fail/issue-52443.rs +++ b/src/test/compile-fail/issue-52443.rs @@ -7,10 +7,5 @@ fn main() { //~^ ERROR `while` is not allowed in a `const` //~| WARN denote infinite loops with [(); { for _ in 0usize.. {}; 0}]; - //~^ ERROR calls in constants are limited to constant functions - //~| ERROR calls in constants are limited to constant functions - //~| ERROR `for` is not allowed in a `const` - //~| ERROR references in constants may only refer to immutable values - //~| ERROR evaluation of constant value failed - //~| ERROR constant contains unimplemented expression type + //~^ ERROR `for` is not allowed in a `const` } diff --git a/src/test/ui/closures/issue-52437.rs b/src/test/ui/closures/issue-52437.rs index 1e649a556e01d..634638e1335b3 100644 --- a/src/test/ui/closures/issue-52437.rs +++ b/src/test/ui/closures/issue-52437.rs @@ -3,4 +3,5 @@ fn main() { //~^ ERROR: invalid label name `'static` //~| ERROR: `loop` is not allowed in a `const` //~| ERROR: type annotations needed + //~| ERROR mismatched types } diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr index b9225e55fe5c7..acb59c7b02d1b 100644 --- a/src/test/ui/closures/issue-52437.stderr +++ b/src/test/ui/closures/issue-52437.stderr @@ -19,7 +19,15 @@ error[E0282]: type annotations needed LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] | ^ consider giving this closure parameter a type -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/issue-52437.rs:2:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[(); _]` + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0282, E0658. +Some errors have detailed explanations: E0282, E0308, E0658. For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index 5b5e431bf2ff6..165d3e1c2e601 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,9 +1,10 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +// build-pass + fn f(x: T) -> [T; N] { [x; N] - //~^ ERROR array lengths can't depend on generic parameters } fn main() { diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr index 949fa896d8780..d48d8ff689462 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-1.stderr @@ -6,11 +6,3 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336-1.rs:5:9 - | -LL | [x; N] - | ^ - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index 7bb36f41b8f9d..c5bf6b6ce94a8 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -2,13 +2,12 @@ //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash fn f(x: T) -> [T; N] { - [x; {N}] - //~^ ERROR array lengths can't depend on generic parameters + [x; { N }] } fn g(x: T) -> [T; N] { - [x; {N}] - //~^ ERROR array lengths can't depend on generic parameters + [x; { N }] + //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied } fn main() { diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index 63f86c81b1e7f..9ced427b93c65 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -6,17 +6,19 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336-2.rs:5:9 +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-61336-2.rs:9:5 | -LL | [x; {N}] - | ^^^ - -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336-2.rs:10:9 +LL | [x; { N }] + | ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | +help: consider restricting this type parameter with `T: std::marker::Copy` + --> $DIR/issue-61336-2.rs:8:6 | -LL | [x; {N}] - | ^^^ +LL | fn g(x: T) -> [T; N] { + | ^ + = note: the `Copy` trait is required because the repeated element will be copied -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs index edc012cbb3d13..7e84e62d8be42 100644 --- a/src/test/ui/const-generics/issues/issue-61336.rs +++ b/src/test/ui/const-generics/issues/issue-61336.rs @@ -3,12 +3,11 @@ fn f(x: T) -> [T; N] { [x; N] - //~^ ERROR array lengths can't depend on generic parameters } fn g(x: T) -> [T; N] { [x; N] - //~^ ERROR array lengths can't depend on generic parameters + //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied } fn main() { diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index f96e8e02d4ec0..ace7955fbdd77 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -6,17 +6,19 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336.rs:5:9 +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/issue-61336.rs:9:5 | LL | [x; N] - | ^ - -error: array lengths can't depend on generic parameters - --> $DIR/issue-61336.rs:10:9 + | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | -LL | [x; N] - | ^ +help: consider restricting this type parameter with `T: std::marker::Copy` + --> $DIR/issue-61336.rs:8:6 + | +LL | fn g(x: T) -> [T; N] { + | ^ + = note: the `Copy` trait is required because the repeated element will be copied -error: aborting due to 2 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs index c5e6fe9104bc9..14b1190df0f99 100644 --- a/src/test/ui/const-generics/issues/issue-62456.rs +++ b/src/test/ui/const-generics/issues/issue-62456.rs @@ -1,9 +1,10 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +// build-pass + fn foo() { let _ = [0u64; N + 1]; - //~^ ERROR array lengths can't depend on generic parameters } fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr index 9cdccf8407c9b..47dd3c01fa9e0 100644 --- a/src/test/ui/const-generics/issues/issue-62456.stderr +++ b/src/test/ui/const-generics/issues/issue-62456.stderr @@ -6,11 +6,3 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: array lengths can't depend on generic parameters - --> $DIR/issue-62456.rs:5:20 - | -LL | let _ = [0u64; N + 1]; - | ^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs index 74ed3d354fc74..cd3cfaac3b95b 100644 --- a/src/test/ui/const-generics/issues/issue-62504.rs +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -16,7 +16,7 @@ struct ArrayHolder([u32; X]); impl ArrayHolder<{ X }> { pub const fn new() -> Self { ArrayHolder([0; Self::SIZE]) - //~^ ERROR: array lengths can't depend on generic parameters + //~^ ERROR: mismatched types } } diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr index c2a752ec1715f..4482389bbdd49 100644 --- a/src/test/ui/const-generics/issues/issue-62504.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.stderr @@ -1,8 +1,12 @@ -error: array lengths can't depend on generic parameters - --> $DIR/issue-62504.rs:18:25 +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 | LL | ArrayHolder([0; Self::SIZE]) - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | + = note: expected array `[u32; _]` + found array `[u32; _]` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs index 79c5ac9dd187e..3d657b0947b18 100644 --- a/src/test/ui/const-generics/issues/issue-67739.rs +++ b/src/test/ui/const-generics/issues/issue-67739.rs @@ -1,5 +1,7 @@ // Regression test for #67739 +// check-pass + #![allow(incomplete_features)] #![feature(const_generics)] @@ -10,7 +12,6 @@ pub trait Trait { fn associated_size(&self) -> usize { [0u8; mem::size_of::()]; - //~^ ERROR: array lengths can't depend on generic parameters 0 } } diff --git a/src/test/ui/const-generics/issues/issue-67739.stderr b/src/test/ui/const-generics/issues/issue-67739.stderr deleted file mode 100644 index a31b556c086f8..0000000000000 --- a/src/test/ui/const-generics/issues/issue-67739.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: array lengths can't depend on generic parameters - --> $DIR/issue-67739.rs:12:15 - | -LL | [0u8; mem::size_of::()]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs index 6fd8e9cbc806b..3ae55ebdbaf35 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs @@ -19,6 +19,7 @@ const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1) as usize]; //~^ ERROR evaluation of constant value failed +//~| ERROR mismatched types fn main() { foo(&A_I8_I[..]); diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr index 2c5b4607aa4d3..94b7c12fc1a8b 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr @@ -4,6 +4,16 @@ error[E0080]: evaluation of constant value failed LL | = [0; (i8::MAX + 1) as usize]; | ^^^^^^^^^^^^^ attempt to add with overflow -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/const-eval-overflow-3.rs:20:7 + | +LL | = [0; (i8::MAX + 1) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `128usize`, found `(i8::MAX + 1) as usize` + | + = note: expected array `[u32; 128]` + found array `[u32; _]` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs index db6f17a671aea..e7b88e00febaa 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.rs @@ -18,6 +18,7 @@ const A_I8_I = [0; (i8::MAX + 1u8) as usize]; //~^ ERROR mismatched types //~| ERROR cannot add `u8` to `i8` +//~| ERROR mismatched types fn main() { foo(&A_I8_I[..]); diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index 3da34fe9af7ec..aebe4feef8d5f 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -12,7 +12,16 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | = help: the trait `std::ops::Add` is not implemented for `i8` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/const-eval-overflow-3b.rs:18:7 + | +LL | = [0; (i8::MAX + 1u8) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `128usize`, found `(i8::MAX + 1u8) as usize` + | + = note: expected array `[u32; 128]` + found array `[u32; _]` + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs index d820c70516124..df4cc8e302677 100644 --- a/src/test/ui/consts/const-eval/issue-52442.rs +++ b/src/test/ui/consts/const-eval/issue-52442.rs @@ -1,6 +1,4 @@ fn main() { [(); { &loop { break } as *const _ as usize } ]; - //~^ ERROR casting pointers to integers in constants is unstable - //~| ERROR `loop` is not allowed in a `const` - //~| ERROR evaluation of constant value failed + //~^ ERROR `loop` is not allowed in a `const` } diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr index eda2dbf0b6b15..0ea974f1f6666 100644 --- a/src/test/ui/consts/const-eval/issue-52442.stderr +++ b/src/test/ui/consts/const-eval/issue-52442.stderr @@ -7,22 +7,6 @@ LL | [(); { &loop { break } as *const _ as usize } ]; = note: see issue #52000 for more information = help: add `#![feature(const_loop)]` to the crate attributes to enable -error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/issue-52442.rs:2:13 - | -LL | [(); { &loop { break } as *const _ as usize } ]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51910 for more information - = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable - -error[E0080]: evaluation of constant value failed - --> $DIR/issue-52442.rs:2:13 - | -LL | [(); { &loop { break } as *const _ as usize } ]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0080, E0658. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs index 80494d1662987..5cfe36f57e647 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.rs +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs @@ -2,7 +2,7 @@ fn main() { // Make sure match uses the usual pointer comparison code path -- i.e., it should complain // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw // bytes. - let _: [u8; 0] = [4; { + let _: [u8; 0] = [4; { //~ ERROR mismatched types match &1 as *const i32 as usize { //~^ ERROR casting pointers to integers in constants //~| ERROR `match` is not allowed in a `const` diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index b47f6d5f845fe..7c4da5e7d86ca 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -28,7 +28,30 @@ error[E0080]: evaluation of constant value failed LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/match-test-ptr-null.rs:5:22 + | +LL | let _: [u8; 0] = [4; { + | ____________-------___^ + | | | + | | expected due to this +LL | | match &1 as *const i32 as usize { +LL | | +LL | | +... | +LL | | } +LL | | }]; + | |______^ expected `0usize`, found `{ + match &1 as *const i32 as usize { + 0 => 42, + n => n, + } + }` + | + = note: expected array `[u8; 0]` + found array `[u8; _]` + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0080, E0658. +Some errors have detailed explanations: E0080, E0308, E0658. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs index 2d4c939f47d79..ded79458e637f 100644 --- a/src/test/ui/consts/issue-52432.rs +++ b/src/test/ui/consts/issue-52432.rs @@ -6,5 +6,4 @@ fn main() { //~| ERROR: type annotations needed [(); &(static || {}) as *const _ as usize]; //~^ ERROR: closures cannot be static - //~| ERROR: evaluation of constant value failed } diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr index e9539d24118a0..d25c11138f400 100644 --- a/src/test/ui/consts/issue-52432.stderr +++ b/src/test/ui/consts/issue-52432.stderr @@ -16,13 +16,7 @@ error[E0282]: type annotations needed LL | [(); &(static |x| {}) as *const _ as usize]; | ^ consider giving this closure parameter a type -error[E0080]: evaluation of constant value failed - --> $DIR/issue-52432.rs:7:10 - | -LL | [(); &(static || {}) as *const _ as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0080, E0282, E0697. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0282, E0697. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/consts/too_generic_eval_ice.rs b/src/test/ui/consts/too_generic_eval_ice.rs index 7a299169bc4e1..7e4d4dbe44610 100644 --- a/src/test/ui/consts/too_generic_eval_ice.rs +++ b/src/test/ui/consts/too_generic_eval_ice.rs @@ -7,6 +7,7 @@ impl Foo { [5; Self::HOST_SIZE] == [6; 0] //~ ERROR no associated item named `HOST_SIZE` //~^ the size for values of type `A` cannot be known //~| the size for values of type `B` cannot be known + //~| binary operation `==` cannot be applied to type `[{integer}; _]` } } diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 8836de0023c9d..ffa28225b79c6 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -41,7 +41,15 @@ LL | [5; Self::HOST_SIZE] == [6; 0] = help: the trait `std::marker::Sized` is not implemented for `B` = note: to learn more, visit -error: aborting due to 3 previous errors +error[E0369]: binary operation `==` cannot be applied to type `[{integer}; _]` + --> $DIR/too_generic_eval_ice.rs:7:30 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | -------------------- ^^ ------ [{integer}; 0] + | | + | [{integer}; _] + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0277, E0599. +Some errors have detailed explanations: E0277, E0369, E0599. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-39559-2.rs b/src/test/ui/issues/issue-39559-2.rs index 3a52e4d6216a5..ec0275b2d6c12 100644 --- a/src/test/ui/issues/issue-39559-2.rs +++ b/src/test/ui/issues/issue-39559-2.rs @@ -17,4 +17,5 @@ fn main() { = [0; Dim3::dim()]; //~^ ERROR E0015 //~| ERROR E0080 + //~| ERROR mismatched types } diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr index 586debbbe5353..7cbf63c2da0a9 100644 --- a/src/test/ui/issues/issue-39559-2.stderr +++ b/src/test/ui/issues/issue-39559-2.stderr @@ -22,7 +22,19 @@ error[E0080]: evaluation of constant value failed LL | = [0; Dim3::dim()]; | ^^^^^^^^^^^ calling non-const function `::dim` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/issue-39559-2.rs:17:11 + | +LL | let array: [usize; Dim3::dim()] + | -------------------- expected due to this +... +LL | = [0; Dim3::dim()]; + | ^^^^^^^^^^^^^^^^ expected `Dim3::dim()`, found `Dim3::dim()` + | + = note: expected array `[usize; _]` + found array `[usize; _]` + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0015, E0080. +Some errors have detailed explanations: E0015, E0080, E0308. For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs index fed08902c8b9d..2688049fcc9ff 100644 --- a/src/test/ui/issues/issue-52060.rs +++ b/src/test/ui/issues/issue-52060.rs @@ -4,5 +4,6 @@ static A: &'static [u32] = &[1]; static B: [u32; 1] = [0; A.len()]; //~^ ERROR [E0013] //~| ERROR evaluation of constant value failed +//~| ERROR mismatched types fn main() {} diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 502825e9766e3..e076e183937f2 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -12,7 +12,16 @@ error[E0080]: evaluation of constant value failed LL | static B: [u32; 1] = [0; A.len()]; | ^ constant accesses static -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/issue-52060.rs:4:22 + | +LL | static B: [u32; 1] = [0; A.len()]; + | ^^^^^^^^^^^^ expected `1usize`, found `A.len()` + | + = note: expected array `[u32; 1]` + found array `[u32; _]` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0013, E0080. +Some errors have detailed explanations: E0013, E0080, E0308. For more information about an error, try `rustc --explain E0013`. diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs index d060f26fb2a08..2c5257ce063cb 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -19,5 +19,4 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` fn main() { let _ = [0; B::VALUE]; - //~^ ERROR array lengths can't depend on generic parameters } diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index c6b2b4d27a208..8ae0f8b804c93 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -13,13 +13,7 @@ LL | type MyA: TraitA; LL | impl TraitB for B { | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation -error: array lengths can't depend on generic parameters - --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17 - | -LL | let _ = [0; B::VALUE]; - | ^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0046, E0437. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr index efad00b272cdc..4a2d1d9f921cb 100644 --- a/src/test/ui/repeat_count.stderr +++ b/src/test/ui/repeat_count.stderr @@ -28,6 +28,12 @@ error[E0308]: mismatched types LL | let e = [0; "foo"]; | ^^^^^ expected `usize`, found `&str` +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:28:17 + | +LL | let g = [0; G { g: () }]; + | ^^^^^^^^^^^ expected `usize`, found struct `main::G` + error[E0308]: mismatched types --> $DIR/repeat_count.rs:19:17 | @@ -50,12 +56,6 @@ help: you can convert an `isize` to `usize` and panic if the converted value wou LL | let f = [0_usize; (-1_isize).try_into().unwrap()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/repeat_count.rs:28:17 - | -LL | let g = [0; G { g: () }]; - | ^^^^^^^^^^^ expected `usize`, found struct `main::G` - error: aborting due to 8 previous errors Some errors have detailed explanations: E0308, E0435. diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs index 63d3431ec9b2f..708d72a2df756 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs @@ -24,6 +24,7 @@ fn i() { static a: [u8; N] = [0; N]; //~^ ERROR can't use generic parameters from outer function //~^^ ERROR can't use generic parameters from outer function + //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr index 82e2aa2db8e25..97c60c7229837 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -48,6 +48,16 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/issue-65035-static-with-parent-generics.rs:24:25 + | +LL | static a: [u8; N] = [0; N]; + | ^^^^^^ expected `N`, found `N` + | + = note: expected array `[u8; _]` + found array `[u8; _]` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0401`. +Some errors have detailed explanations: E0308, E0401. +For more information about an error, try `rustc --explain E0308`. From fa5a15c7d507f8d2d27770602101b9d0b5cc71bc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 14 Mar 2020 15:53:00 +0100 Subject: [PATCH 19/30] Document most methods on `ty::Const` --- src/librustc/ty/sty.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5d1f6ae387740..7200ebef9405f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2422,6 +2422,8 @@ fn const_param_def_id(expr: &hir::Expr<'_>) -> Option { } impl<'tcx> Const<'tcx> { + /// Literals and const generic parameters are eagerly converted to a constant, everything else + /// becomes `Unevaluated`. pub fn from_hir_anon_const( tcx: TyCtxt<'tcx>, ast_const: &hir::AnonConst, @@ -2471,16 +2473,19 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Interns the given value as a constant. pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { tcx.mk_const(Self { val: ConstKind::Value(val), ty }) } #[inline] + /// Interns the given scalar as a constant. pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { Self::from_value(tcx, ConstValue::Scalar(val), ty) } #[inline] + /// Creates a constant with the given integer value and interns it. pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self { let size = tcx .layout_of(ty) @@ -2490,21 +2495,27 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Creates an interned zst constant. pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { Self::from_scalar(tcx, Scalar::zst(), ty) } #[inline] + /// Creates an interned bool constant. pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> &'tcx Self { Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) } #[inline] + /// Creates an interned usize constant. pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> &'tcx Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } #[inline] + /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of + /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it + /// contains const generic parameters or pointers). pub fn try_eval_bits( &self, tcx: TyCtxt<'tcx>, @@ -2518,6 +2529,8 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the + /// unevaluated constant. pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> { let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| { let param_env_and_substs = param_env.with_reveal_all().and(substs); @@ -2574,12 +2587,14 @@ impl<'tcx> Const<'tcx> { } #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { self.try_eval_bits(tcx, param_env, ty) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) } #[inline] + /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { self.eval_bits(tcx, param_env, tcx.types.usize) as u64 } From 3f89c38bc0231f08e0eee6fa9942e7c71b5544f3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 14 Mar 2020 20:12:54 +0100 Subject: [PATCH 20/30] Inline `const_param_def_id` at its only use site --- src/librustc/ty/sty.rs | 62 ++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7200ebef9405f..9e0f4668d95a1 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2401,26 +2401,6 @@ pub struct Const<'tcx> { #[cfg(target_arch = "x86_64")] static_assert_size!(Const<'_>, 48); -/// Returns the `DefId` of the constant parameter that the provided expression is a path to. -fn const_param_def_id(expr: &hir::Expr<'_>) -> Option { - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - - match &expr.kind { - hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res { - hir::def::Res::Def(hir::def::DefKind::ConstParam, did) => Some(did), - _ => None, - }, - _ => None, - } -} - impl<'tcx> Const<'tcx> { /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. @@ -2456,20 +2436,36 @@ impl<'tcx> Const<'tcx> { } } - let kind = if let Some(def_id) = const_param_def_id(expr) { - // Find the name and index of the const parameter by indexing the generics of the - // parent item and construct a `ParamConst`. - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let item_id = tcx.hir().get_parent_node(hir_id); - let item_def_id = tcx.hir().local_def_id(item_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; - let name = tcx.hir().name(hir_id); - ty::ConstKind::Param(ty::ParamConst::new(index, name)) - } else { - ty::ConstKind::Unevaluated(def_id, InternalSubsts::identity_for_item(tcx, def_id), None) + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, }; - tcx.mk_const(ty::Const { val: kind, ty }) + + use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; + let val = match expr.kind { + ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + let item_id = tcx.hir().get_parent_node(hir_id); + let item_def_id = tcx.hir().local_def_id(item_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; + let name = tcx.hir().name(hir_id); + ty::ConstKind::Param(ty::ParamConst::new(index, name)) + } + _ => ty::ConstKind::Unevaluated( + def_id, + InternalSubsts::identity_for_item(tcx, def_id), + None, + ), + }; + + tcx.mk_const(ty::Const { val, ty }) } #[inline] From 770be24ccd9c47c05aceff91ce5a081798d97c67 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 17 Mar 2020 18:54:20 +0100 Subject: [PATCH 21/30] Use `DefId`s to identify anon consts when converting from HIR to ty::Const --- src/librustc/ty/sty.rs | 14 ++++++-------- src/librustc_mir_build/hair/cx/expr.rs | 1 + src/librustc_typeck/astconv.rs | 4 +++- src/librustc_typeck/check/mod.rs | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 9e0f4668d95a1..e5c88c1c9ba94 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2404,16 +2404,14 @@ static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. - pub fn from_hir_anon_const( - tcx: TyCtxt<'tcx>, - ast_const: &hir::AnonConst, - ty: Ty<'tcx>, - ) -> &'tcx Self { - debug!("Const::from_hir_anon_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const); + pub fn from_hir_anon_const(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Ty<'tcx>) -> &'tcx Self { + debug!("Const::from_hir_anon_const(id={:?})", def_id); + + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let def_id = tcx.hir().local_def_id(ast_const.hir_id); + let body_id = tcx.hir().body_owned_by(hir_id); - let expr = &tcx.hir().body(ast_const.body).value; + let expr = &tcx.hir().body(body_id).value; let lit_input = match expr.kind { hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index b9c9e9834eff8..73c442e4a91ce 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -406,6 +406,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { + let count = cx.tcx.hir().local_def_id(count.hir_id); let count = ty::Const::from_hir_anon_const(cx.tcx, count, cx.tcx.types.usize); ExprKind::Repeat { value: v.to_ref(), count } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2d7bf81aedd6d..ee7134822682a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -780,7 +780,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - ty::Const::from_hir_anon_const(tcx, &ct.value, tcx.type_of(param.def_id)).into() + let ct = tcx.hir().local_def_id(ct.value.hir_id); + ty::Const::from_hir_anon_const(tcx, ct, tcx.type_of(param.def_id)).into() } _ => unreachable!(), }, @@ -2764,6 +2765,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .unwrap_or(tcx.types.err) } hir::TyKind::Array(ref ty, ref length) => { + let length = tcx.hir().local_def_id(length.hir_id); let length = ty::Const::from_hir_anon_const(tcx, length, tcx.types.usize); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 292ad1e94a72e..f790bcfbb09aa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3280,7 +3280,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - ty::Const::from_hir_anon_const(self.tcx, ast_c, ty) + let c = self.tcx.hir().local_def_id(ast_c.hir_id); + ty::Const::from_hir_anon_const(self.tcx, c, ty) } // If the type given by the user has free regions, save it for later, since From c3b98813c42ae0a0da402f1a933ad7c24b1c1c43 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 11 Mar 2020 22:24:20 +0000 Subject: [PATCH 22/30] Remove `ReClosureBound` --- src/librustc/ich/impls_ty.rs | 3 -- src/librustc/mir/query.rs | 49 +++++++++---------- src/librustc/ty/print/pretty.rs | 8 +-- src/librustc/ty/structural_impls.rs | 2 - src/librustc/ty/sty.rs | 10 ---- .../infer/canonical/canonicalizer.rs | 4 -- src/librustc_infer/infer/combine.rs | 4 -- .../infer/error_reporting/mod.rs | 5 -- src/librustc_infer/infer/freshen.rs | 4 -- .../infer/lexical_region_resolve/mod.rs | 7 +-- .../infer/region_constraints/mod.rs | 2 +- .../borrow_check/diagnostics/region_name.rs | 3 +- .../borrow_check/region_infer/mod.rs | 41 +++------------- src/librustc_trait_selection/opaque_types.rs | 6 +-- src/librustc_typeck/outlives/utils.rs | 1 - src/librustc_typeck/variance/constraints.rs | 1 - src/librustdoc/clean/mod.rs | 1 - .../projection-one-region-closure.stderr | 2 +- ...tion-one-region-trait-bound-closure.stderr | 2 +- ...tion-two-region-trait-bound-closure.stderr | 24 ++++----- 20 files changed, 50 insertions(+), 129 deletions(-) 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/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 cb01d821c1871..301254d4f0ded 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1547,7 +1547,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, } } @@ -1659,12 +1659,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 e265a2f8257fb..7f0ee1a86197b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1442,12 +1442,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> {} @@ -1689,7 +1683,6 @@ impl RegionKind { RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(), RegionKind::ReEmpty(_) => false, RegionKind::ReErased => false, - RegionKind::ReClosureBound(..) => false, } } @@ -1770,9 +1763,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_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index 964e378f7abc8..ad23ecc1e3647 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 a544381f33da1..239b67a1da3ff 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 b7278ecd5e407..dfad3d8e26f3d 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -464,12 +464,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 868b95043796b..e9ad7313ea0e2 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_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 7103fc596c922..2d0ccd4a98869 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_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 6cf1302783c0b..9367616e71a61 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -823,11 +823,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_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 c4ad4554a0048..c16cf9ac10c72 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/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 118a849f98416..2bdb5384800a5 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 @@ -108,7 +108,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, 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 59d8aa484bdac..1ed4c519d2bbd 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 @@ -90,7 +90,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, 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 ff402f89ae861..b1ee9fac5f973 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 @@ -10,7 +10,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 @@ -26,13 +26,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 @@ -45,7 +45,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, 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 @@ -61,13 +61,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 @@ -80,7 +80,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, 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 @@ -107,7 +107,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, 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 @@ -134,7 +134,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, 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 @@ -162,7 +162,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 @@ -202,7 +202,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, 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 @@ -229,7 +229,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, 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 From 9bcd9fe6743aabcf6d96b3fafcd86d1e36114eed Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Mar 2020 19:19:07 +0100 Subject: [PATCH 23/30] Address review comments --- src/librustc/ty/sty.rs | 14 ++++++++------ src/librustc_mir_build/hair/cx/expr.rs | 4 ++-- src/librustc_typeck/astconv.rs | 8 ++++---- src/librustc_typeck/check/expr.rs | 3 +-- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/mod.rs | 8 ++++---- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e5c88c1c9ba94..ed4417978747e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -20,7 +20,7 @@ use polonius_engine::Atom; use rustc_ast::ast::{self, Ident}; use rustc_data_structures::captures::Captures; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::vec::Idx; use rustc_macros::HashStable; use rustc_span::symbol::{kw, Symbol}; @@ -2404,15 +2404,17 @@ static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. - pub fn from_hir_anon_const(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Ty<'tcx>) -> &'tcx Self { - debug!("Const::from_hir_anon_const(id={:?})", def_id); + pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + debug!("Const::from_anon_const(id={:?})", def_id); - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let body_id = tcx.hir().body_owned_by(hir_id); let expr = &tcx.hir().body(body_id).value; + let ty = tcx.type_of(def_id.to_def_id()); + let lit_input = match expr.kind { hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind { @@ -2457,8 +2459,8 @@ impl<'tcx> Const<'tcx> { ty::ConstKind::Param(ty::ParamConst::new(index, name)) } _ => ty::ConstKind::Unevaluated( - def_id, - InternalSubsts::identity_for_item(tcx, def_id), + def_id.to_def_id(), + InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), None, ), }; diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 73c442e4a91ce..a45c30890645a 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -406,8 +406,8 @@ fn make_mirror_unadjusted<'a, 'tcx>( // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, ref count) => { - let count = cx.tcx.hir().local_def_id(count.hir_id); - let count = ty::Const::from_hir_anon_const(cx.tcx, count, cx.tcx.types.usize); + let count_def_id = cx.tcx.hir().local_def_id(count.hir_id).expect_local(); + let count = ty::Const::from_anon_const(cx.tcx, count_def_id); ExprKind::Repeat { value: v.to_ref(), count } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ee7134822682a..1aa920213933e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -780,8 +780,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - let ct = tcx.hir().local_def_id(ct.value.hir_id); - ty::Const::from_hir_anon_const(tcx, ct, tcx.type_of(param.def_id)).into() + let ct_def_id = tcx.hir().local_def_id(ct.value.hir_id).expect_local(); + ty::Const::from_anon_const(tcx, ct_def_id).into() } _ => unreachable!(), }, @@ -2765,8 +2765,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .unwrap_or(tcx.types.err) } hir::TyKind::Array(ref ty, ref length) => { - let length = tcx.hir().local_def_id(length.hir_id); - let length = ty::Const::from_hir_anon_const(tcx, length, tcx.types.usize); + let length_def_id = tcx.hir().local_def_id(length.hir_id).expect_local(); + let length = ty::Const::from_anon_const(tcx, length_def_id); let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length)); self.normalize_ty(ast_ty.span, array_ty) } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index e57e6cd80ca14..77a8e92c379d9 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1007,8 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let count_def_id = tcx.hir().local_def_id(count.hir_id); - let count = self.to_const(count, tcx.type_of(count_def_id)); + let count = self.to_const(count); let uty = match expected { ExpectHasType(uty) => match uty.kind { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 48c72567b5c31..d340d6ff5c271 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -331,7 +331,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => self.to_ty(ty).into(), (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into() + self.to_const(&ct.value).into() } _ => unreachable!(), }, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f790bcfbb09aa..6f0f69a7943f9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3279,9 +3279,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } - pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - let c = self.tcx.hir().local_def_id(ast_c.hir_id); - ty::Const::from_hir_anon_const(self.tcx, c, ty) + pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> { + let c = self.tcx.hir().local_def_id(ast_c.hir_id).expect_local(); + ty::Const::from_anon_const(self.tcx, c) } // If the type given by the user has free regions, save it for later, since @@ -5510,7 +5510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.to_ty(ty).into() } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { - self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into() + self.to_const(&ct.value).into() } _ => unreachable!(), }, From c7c2fa102463f484348850c6a8c8850abed486c2 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Mar 2020 00:24:47 +0100 Subject: [PATCH 24/30] Make `needs_drop` less pessimistic on generators --- src/librustc/ty/util.rs | 8 +++----- src/librustc_ty/needs_drop.rs | 17 +++++++++++++++++ src/test/ui/generator/borrowing.stderr | 15 ++++++--------- src/test/ui/generator/retain-resume-ref.stderr | 7 +++---- 4 files changed, 29 insertions(+), 18 deletions(-) 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_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index 37af8168f87d9..cbbb2aa19fd83 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -99,6 +99,23 @@ where } } + ty::Generator(def_id, substs, _) => { + let substs = substs.as_generator(); + for upvar_ty in substs.upvar_tys(def_id, tcx) { + queue_type(self, upvar_ty); + } + + let witness = substs.witness(def_id, tcx); + 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/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 From 9ebc72fdf0422e1a1fe7925e0a203b42b76f54f2 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Mar 2020 02:28:48 +0100 Subject: [PATCH 25/30] Adjust mir-opt test and make it drop something --- src/test/mir-opt/generator-drop-cleanup.rs | 45 ++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) 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 From 124ab20d4bbbe28d50b641836e3a87f1d796767d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Mar 2020 19:35:19 +0100 Subject: [PATCH 26/30] Limit `from_anon_const` to `AnonConst`s. --- src/librustc/ty/sty.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ed4417978747e..e49a29f687c23 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2409,7 +2409,10 @@ impl<'tcx> Const<'tcx> { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let body_id = tcx.hir().body_owned_by(hir_id); + let body_id = match tcx.hir().get(hir_id) { + hir::Node::AnonConst(ac) => ac.body, + _ => span_bug!(tcx.def_span(def_id.to_def_id()), "from_anon_const can only process anonymous constants"), + }; let expr = &tcx.hir().body(body_id).value; From 1df764174d389849af8f36cc924da28bbc802b91 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 23 Mar 2020 19:47:24 +0100 Subject: [PATCH 27/30] Fix rebase fallout --- src/librustc_ty/needs_drop.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index cbbb2aa19fd83..f8149cdce4d30 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -99,13 +99,13 @@ where } } - ty::Generator(def_id, substs, _) => { + ty::Generator(_, substs, _) => { let substs = substs.as_generator(); - for upvar_ty in substs.upvar_tys(def_id, tcx) { + for upvar_ty in substs.upvar_tys() { queue_type(self, upvar_ty); } - let witness = substs.witness(def_id, tcx); + let witness = substs.witness(); let interior_tys = match &witness.kind { ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys), _ => bug!(), From e75158d4861e8cd0b0f8a11f360714c56577ba1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 22 Mar 2020 18:50:30 -0700 Subject: [PATCH 28/30] Account for bad placeholder types in where clauses --- src/librustc_typeck/astconv.rs | 34 +++--- src/librustc_typeck/check/mod.rs | 9 +- src/librustc_typeck/collect.rs | 22 ++-- src/test/ui/did_you_mean/bad-assoc-ty.rs | 32 +++++ src/test/ui/did_you_mean/bad-assoc-ty.stderr | 110 +++++++++++++++++- .../ui/typeck/typeck_type_placeholder_item.rs | 5 - .../typeck_type_placeholder_item.stderr | 66 +++-------- 7 files changed, 192 insertions(+), 86 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3ee6d5df7356b..378a68315b289 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, @@ -2739,7 +2727,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) @@ -2922,7 +2916,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"); @@ -2934,6 +2928,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) => { @@ -2955,7 +2951,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(), ); @@ -2981,8 +2977,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 { @@ -2993,8 +2988,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 e4bd42f61c321..ce0be5083573c 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 a79c065307796..2de43a6b1ef15 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1502,7 +1502,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), ), } @@ -1513,14 +1513,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); @@ -2142,7 +2137,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/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/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`. From 5aa15bfa1c54d3139559e7296ff2b74ebedcc07e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Mar 2020 22:24:31 +0100 Subject: [PATCH 29/30] Remove leftover mentions of `from_anon_const` --- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index dfe5adb1bbff0..4ca9ad46daa95 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -151,7 +151,7 @@ pub struct LitToConstInput<'tcx> { pub enum LitToConstError { /// The literal's inferred type did not match the expected `ty` in the input. /// This is used for graceful error handling (`delay_span_bug`) in - /// type checking (`AstConv::ast_const_to_const`). + /// type checking (`Const::from_anon_const`). TypeError, UnparseableFloat, Reported, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e49a29f687c23..73fe15d9a1737 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2435,7 +2435,7 @@ impl<'tcx> Const<'tcx> { if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { return c; } else { - tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const"); + tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const"); } } diff --git a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs index 98be8c345a9ed..f0d5fea8e0239 100644 --- a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs +++ b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs @@ -3,7 +3,7 @@ // we call the query `lit_to_const(input);`. // However, the literal `input.lit` would not be of the type expected by `input.ty`. // As a result, we immediately called `bug!(...)` instead of bubbling up the problem -// so that it could be handled by the caller of `lit_to_const` (`ast_const_to_const`). +// so that it could be handled by the caller of `lit_to_const` (`from_anon_const`). fn main() {} From 4f513b5fd7945937cba8bbfab84ae33e14642b85 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Mar 2020 22:39:59 +0100 Subject: [PATCH 30/30] Split out some impls from rustc::mir into a separate submodule --- src/librustc/mir/mod.rs | 323 +----------------------------- src/librustc/mir/type_foldable.rs | 322 +++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+), 322 deletions(-) create mode 100644 src/librustc/mir/type_foldable.rs diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d81b940cbe797..63019c57b2fcc 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -45,6 +45,7 @@ pub mod mono; mod query; pub mod tcx; pub mod traversal; +mod type_foldable; pub mod visit; /// Types for locals @@ -2683,325 +2684,3 @@ impl Location { } } } - -/* - * `TypeFoldable` implementations for MIR types -*/ - -CloneTypeFoldableAndLiftImpls! { - BlockTailInfo, - MirPhase, - SourceInfo, - FakeReadCause, - RetagKind, - SourceScope, - SourceScopeData, - SourceScopeLocalData, - UserTypeAnnotationIndex, -} - -impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - use crate::mir::TerminatorKind::*; - - let kind = match self.kind { - Goto { target } => Goto { target }, - SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt { - discr: discr.fold_with(folder), - switch_ty: switch_ty.fold_with(folder), - values: values.clone(), - targets: targets.clone(), - }, - Drop { ref location, target, unwind } => { - Drop { location: location.fold_with(folder), target, unwind } - } - DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace { - location: location.fold_with(folder), - value: value.fold_with(folder), - target, - unwind, - }, - Yield { ref value, resume, ref resume_arg, drop } => Yield { - value: value.fold_with(folder), - resume, - resume_arg: resume_arg.fold_with(folder), - drop, - }, - Call { ref func, ref args, ref destination, cleanup, from_hir_call } => { - let dest = - destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); - - Call { - func: func.fold_with(folder), - args: args.fold_with(folder), - destination: dest, - cleanup, - from_hir_call, - } - } - Assert { ref cond, expected, ref msg, target, cleanup } => { - use AssertKind::*; - let msg = match msg { - BoundsCheck { ref len, ref index } => { - BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } - } - Overflow(_) - | OverflowNeg - | DivisionByZero - | RemainderByZero - | ResumedAfterReturn(_) - | ResumedAfterPanic(_) => msg.clone(), - }; - Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } - } - GeneratorDrop => GeneratorDrop, - Resume => Resume, - Abort => Abort, - Return => Return, - Unreachable => Unreachable, - FalseEdges { real_target, imaginary_target } => { - FalseEdges { real_target, imaginary_target } - } - FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, - }; - Terminator { source_info: self.source_info, kind } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - use crate::mir::TerminatorKind::*; - - match self.kind { - SwitchInt { ref discr, switch_ty, .. } => { - discr.visit_with(visitor) || switch_ty.visit_with(visitor) - } - Drop { ref location, .. } => location.visit_with(visitor), - DropAndReplace { ref location, ref value, .. } => { - location.visit_with(visitor) || value.visit_with(visitor) - } - Yield { ref value, .. } => value.visit_with(visitor), - Call { ref func, ref args, ref destination, .. } => { - let dest = if let Some((ref loc, _)) = *destination { - loc.visit_with(visitor) - } else { - false - }; - dest || func.visit_with(visitor) || args.visit_with(visitor) - } - Assert { ref cond, ref msg, .. } => { - if cond.visit_with(visitor) { - use AssertKind::*; - match msg { - BoundsCheck { ref len, ref index } => { - len.visit_with(visitor) || index.visit_with(visitor) - } - Overflow(_) - | OverflowNeg - | DivisionByZero - | RemainderByZero - | ResumedAfterReturn(_) - | ResumedAfterPanic(_) => false, - } - } else { - false - } - } - Goto { .. } - | Resume - | Abort - | Return - | GeneratorDrop - | Unreachable - | FalseEdges { .. } - | FalseUnwind { .. } => false, - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { - fn super_fold_with>(&self, _: &mut F) -> Self { - *self - } - - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.local.visit_with(visitor) || self.projection.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); - folder.tcx().intern_place_elems(&v) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) - } -} - -impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - use crate::mir::Rvalue::*; - match *self { - Use(ref op) => Use(op.fold_with(folder)), - Repeat(ref op, len) => Repeat(op.fold_with(folder), len), - Ref(region, bk, ref place) => { - Ref(region.fold_with(folder), bk, place.fold_with(folder)) - } - AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)), - Len(ref place) => Len(place.fold_with(folder)), - Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), - BinaryOp(op, ref rhs, ref lhs) => { - BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) - } - CheckedBinaryOp(op, ref rhs, ref lhs) => { - CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) - } - UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)), - Discriminant(ref place) => Discriminant(place.fold_with(folder)), - NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), - Aggregate(ref kind, ref fields) => { - let kind = box match **kind { - AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), - AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( - def, - v, - substs.fold_with(folder), - user_ty.fold_with(folder), - n, - ), - AggregateKind::Closure(id, substs) => { - AggregateKind::Closure(id, substs.fold_with(folder)) - } - AggregateKind::Generator(id, substs, movablity) => { - AggregateKind::Generator(id, substs.fold_with(folder), movablity) - } - }; - Aggregate(kind, fields.fold_with(folder)) - } - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - use crate::mir::Rvalue::*; - match *self { - Use(ref op) => op.visit_with(visitor), - Repeat(ref op, _) => op.visit_with(visitor), - Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), - AddressOf(_, ref place) => place.visit_with(visitor), - Len(ref place) => place.visit_with(visitor), - Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), - BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { - rhs.visit_with(visitor) || lhs.visit_with(visitor) - } - UnaryOp(_, ref val) => val.visit_with(visitor), - Discriminant(ref place) => place.visit_with(visitor), - NullaryOp(_, ty) => ty.visit_with(visitor), - Aggregate(ref kind, ref fields) => { - (match **kind { - AggregateKind::Array(ty) => ty.visit_with(visitor), - AggregateKind::Tuple => false, - AggregateKind::Adt(_, _, substs, user_ty, _) => { - substs.visit_with(visitor) || user_ty.visit_with(visitor) - } - AggregateKind::Closure(_, substs) => substs.visit_with(visitor), - AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), - }) || fields.visit_with(visitor) - } - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - match *self { - Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)), - Operand::Move(ref place) => Operand::Move(place.fold_with(folder)), - Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - match *self { - Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), - Operand::Constant(ref c) => c.visit_with(visitor), - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - use crate::mir::ProjectionElem::*; - - match *self { - Deref => Deref, - Field(f, ty) => Field(f, ty.fold_with(folder)), - Index(v) => Index(v.fold_with(folder)), - Downcast(symbol, variantidx) => Downcast(symbol, variantidx), - ConstantIndex { offset, min_length, from_end } => { - ConstantIndex { offset, min_length, from_end } - } - Subslice { from, to, from_end } => Subslice { from, to, from_end }, - } - } - - fn super_visit_with>(&self, visitor: &mut Vs) -> bool { - use crate::mir::ProjectionElem::*; - - match self { - Field(_, ty) => ty.visit_with(visitor), - Index(v) => v.visit_with(visitor), - _ => false, - } - } -} - -impl<'tcx> TypeFoldable<'tcx> for Field { - fn super_fold_with>(&self, _: &mut F) -> Self { - *self - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { - fn super_fold_with>(&self, _: &mut F) -> Self { - *self - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { - fn super_fold_with>(&self, _: &mut F) -> Self { - self.clone() - } - fn super_visit_with>(&self, _: &mut V) -> bool { - false - } -} - -impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn super_fold_with>(&self, folder: &mut F) -> Self { - Constant { - span: self.span, - user_ty: self.user_ty.fold_with(folder), - literal: self.literal.fold_with(folder), - } - } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.literal.visit_with(visitor) - } -} diff --git a/src/librustc/mir/type_foldable.rs b/src/librustc/mir/type_foldable.rs new file mode 100644 index 0000000000000..9520f081b6bfb --- /dev/null +++ b/src/librustc/mir/type_foldable.rs @@ -0,0 +1,322 @@ +//! `TypeFoldable` implementations for MIR types + +use super::*; +use crate::ty; + +CloneTypeFoldableAndLiftImpls! { + BlockTailInfo, + MirPhase, + SourceInfo, + FakeReadCause, + RetagKind, + SourceScope, + SourceScopeData, + SourceScopeLocalData, + UserTypeAnnotationIndex, +} + +impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + use crate::mir::TerminatorKind::*; + + let kind = match self.kind { + Goto { target } => Goto { target }, + SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt { + discr: discr.fold_with(folder), + switch_ty: switch_ty.fold_with(folder), + values: values.clone(), + targets: targets.clone(), + }, + Drop { ref location, target, unwind } => { + Drop { location: location.fold_with(folder), target, unwind } + } + DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace { + location: location.fold_with(folder), + value: value.fold_with(folder), + target, + unwind, + }, + Yield { ref value, resume, ref resume_arg, drop } => Yield { + value: value.fold_with(folder), + resume, + resume_arg: resume_arg.fold_with(folder), + drop, + }, + Call { ref func, ref args, ref destination, cleanup, from_hir_call } => { + let dest = + destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest)); + + Call { + func: func.fold_with(folder), + args: args.fold_with(folder), + destination: dest, + cleanup, + from_hir_call, + } + } + Assert { ref cond, expected, ref msg, target, cleanup } => { + use AssertKind::*; + let msg = match msg { + BoundsCheck { ref len, ref index } => { + BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } + } + Overflow(_) + | OverflowNeg + | DivisionByZero + | RemainderByZero + | ResumedAfterReturn(_) + | ResumedAfterPanic(_) => msg.clone(), + }; + Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } + } + GeneratorDrop => GeneratorDrop, + Resume => Resume, + Abort => Abort, + Return => Return, + Unreachable => Unreachable, + FalseEdges { real_target, imaginary_target } => { + FalseEdges { real_target, imaginary_target } + } + FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, + }; + Terminator { source_info: self.source_info, kind } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + use crate::mir::TerminatorKind::*; + + match self.kind { + SwitchInt { ref discr, switch_ty, .. } => { + discr.visit_with(visitor) || switch_ty.visit_with(visitor) + } + Drop { ref location, .. } => location.visit_with(visitor), + DropAndReplace { ref location, ref value, .. } => { + location.visit_with(visitor) || value.visit_with(visitor) + } + Yield { ref value, .. } => value.visit_with(visitor), + Call { ref func, ref args, ref destination, .. } => { + let dest = if let Some((ref loc, _)) = *destination { + loc.visit_with(visitor) + } else { + false + }; + dest || func.visit_with(visitor) || args.visit_with(visitor) + } + Assert { ref cond, ref msg, .. } => { + if cond.visit_with(visitor) { + use AssertKind::*; + match msg { + BoundsCheck { ref len, ref index } => { + len.visit_with(visitor) || index.visit_with(visitor) + } + Overflow(_) + | OverflowNeg + | DivisionByZero + | RemainderByZero + | ResumedAfterReturn(_) + | ResumedAfterPanic(_) => false, + } + } else { + false + } + } + Goto { .. } + | Resume + | Abort + | Return + | GeneratorDrop + | Unreachable + | FalseEdges { .. } + | FalseUnwind { .. } => false, + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { + fn super_fold_with>(&self, _: &mut F) -> Self { + *self + } + + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.local.visit_with(visitor) || self.projection.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + let v = self.iter().map(|t| t.fold_with(folder)).collect::>(); + folder.tcx().intern_place_elems(&v) + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.iter().any(|t| t.visit_with(visitor)) + } +} + +impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + use crate::mir::Rvalue::*; + match *self { + Use(ref op) => Use(op.fold_with(folder)), + Repeat(ref op, len) => Repeat(op.fold_with(folder), len), + Ref(region, bk, ref place) => { + Ref(region.fold_with(folder), bk, place.fold_with(folder)) + } + AddressOf(mutability, ref place) => AddressOf(mutability, place.fold_with(folder)), + Len(ref place) => Len(place.fold_with(folder)), + Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), + BinaryOp(op, ref rhs, ref lhs) => { + BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + } + CheckedBinaryOp(op, ref rhs, ref lhs) => { + CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)) + } + UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)), + Discriminant(ref place) => Discriminant(place.fold_with(folder)), + NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), + Aggregate(ref kind, ref fields) => { + let kind = box match **kind { + AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), + AggregateKind::Tuple => AggregateKind::Tuple, + AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( + def, + v, + substs.fold_with(folder), + user_ty.fold_with(folder), + n, + ), + AggregateKind::Closure(id, substs) => { + AggregateKind::Closure(id, substs.fold_with(folder)) + } + AggregateKind::Generator(id, substs, movablity) => { + AggregateKind::Generator(id, substs.fold_with(folder), movablity) + } + }; + Aggregate(kind, fields.fold_with(folder)) + } + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + use crate::mir::Rvalue::*; + match *self { + Use(ref op) => op.visit_with(visitor), + Repeat(ref op, _) => op.visit_with(visitor), + Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), + AddressOf(_, ref place) => place.visit_with(visitor), + Len(ref place) => place.visit_with(visitor), + Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), + BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { + rhs.visit_with(visitor) || lhs.visit_with(visitor) + } + UnaryOp(_, ref val) => val.visit_with(visitor), + Discriminant(ref place) => place.visit_with(visitor), + NullaryOp(_, ty) => ty.visit_with(visitor), + Aggregate(ref kind, ref fields) => { + (match **kind { + AggregateKind::Array(ty) => ty.visit_with(visitor), + AggregateKind::Tuple => false, + AggregateKind::Adt(_, _, substs, user_ty, _) => { + substs.visit_with(visitor) || user_ty.visit_with(visitor) + } + AggregateKind::Closure(_, substs) => substs.visit_with(visitor), + AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), + }) || fields.visit_with(visitor) + } + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match *self { + Operand::Copy(ref place) => Operand::Copy(place.fold_with(folder)), + Operand::Move(ref place) => Operand::Move(place.fold_with(folder)), + Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match *self { + Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor), + Operand::Constant(ref c) => c.visit_with(visitor), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + use crate::mir::ProjectionElem::*; + + match *self { + Deref => Deref, + Field(f, ty) => Field(f, ty.fold_with(folder)), + Index(v) => Index(v.fold_with(folder)), + Downcast(symbol, variantidx) => Downcast(symbol, variantidx), + ConstantIndex { offset, min_length, from_end } => { + ConstantIndex { offset, min_length, from_end } + } + Subslice { from, to, from_end } => Subslice { from, to, from_end }, + } + } + + fn super_visit_with>(&self, visitor: &mut Vs) -> bool { + use crate::mir::ProjectionElem::*; + + match self { + Field(_, ty) => ty.visit_with(visitor), + Index(v) => v.visit_with(visitor), + _ => false, + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Field { + fn super_fold_with>(&self, _: &mut F) -> Self { + *self + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { + fn super_fold_with>(&self, _: &mut F) -> Self { + *self + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { + fn super_fold_with>(&self, _: &mut F) -> Self { + self.clone() + } + fn super_visit_with>(&self, _: &mut V) -> bool { + false + } +} + +impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Constant { + span: self.span, + user_ty: self.user_ty.fold_with(folder), + literal: self.literal.fold_with(folder), + } + } + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.literal.visit_with(visitor) + } +}