From a0df4204c49975d3a5fb9c3a6562d49faf130b01 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 17 Oct 2018 15:51:10 +0200 Subject: [PATCH 01/33] Implement FromStr for PathBuf Initially landed in https://github.com/rust-lang/rust/pull/48292 and reverted in https://github.com/rust-lang/rust/pull/50401. This time, use `std::string::ParseError` as suggested in https://github.com/rust-lang/rust/issues/44431#issuecomment-428112632 --- src/libstd/path.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index ca8be75fab5be..a153456370c6f 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -87,6 +87,8 @@ use io; use iter::{self, FusedIterator}; use ops::{self, Deref}; use rc::Rc; +use str::FromStr; +use string::ParseError; use sync::Arc; use ffi::{OsStr, OsString}; @@ -1443,6 +1445,15 @@ impl From for PathBuf { } } +#[stable(feature = "path_from_str", since = "1.26.0")] +impl FromStr for PathBuf { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + Ok(PathBuf::from(s)) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl> iter::FromIterator

for PathBuf { fn from_iter>(iter: I) -> PathBuf { From ac186354354e6032c34ad95ce22d526371729cb6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 21 Oct 2018 23:54:35 +0200 Subject: [PATCH 02/33] Add MaybeUninit::new Sometimes it *is* initialized! --- src/libcore/lib.rs | 1 + src/libcore/mem.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 59cc312bee5fc..1eded42683073 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -82,6 +82,7 @@ #![feature(const_fn)] #![feature(const_int_ops)] #![feature(const_fn_union)] +#![feature(const_manually_drop_new)] #![feature(custom_attribute)] #![feature(doc_cfg)] #![feature(doc_spotlight)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 27ee9556bd089..a955e0e662a6c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1021,6 +1021,15 @@ pub union MaybeUninit { } impl MaybeUninit { + /// Create a new `MaybeUninit` initialized with the given value. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub const fn new(val: T) -> MaybeUninit { + MaybeUninit { value: ManuallyDrop::new(val) } + } + /// Create a new `MaybeUninit` in an uninitialized state. /// /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. From 412ad9bf3746bd0682db136c36a433f3205715f1 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Sun, 21 Oct 2018 20:09:42 -0700 Subject: [PATCH 03/33] Allow extern statics with an extern type Fixes #55239 --- src/librustc_typeck/check/wfcheck.rs | 42 +++++++++++++++--------- src/test/ui/static/static-extern-type.rs | 37 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/static/static-extern-type.rs diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec773e384af38..ec6ca242fa36b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -13,7 +13,7 @@ use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; +use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; @@ -119,14 +119,14 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def check_item_fn(tcx, item); } hir::ItemKind::Static(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::Const(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() { if let hir::ForeignItemKind::Static(ref ty, ..) = it.node { - check_item_type(tcx, it.id, ty.span); + check_item_type(tcx, it.id, ty.span, true); } }, hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { @@ -340,23 +340,35 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, ty_span: Span) { +fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); - fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); - fcx.register_bound( - item_ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), - ); + let mut allow_unsized = false; + if allow_foreign_ty { + if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { + allow_unsized = true; + } + } + + if !allow_unsized { + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + fcx.register_bound( + item_ty, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + traits::ObligationCause::new( + ty_span, + fcx.body_id, + traits::MiscObligation, + ), + ); + } vec![] // no implied bounds in a const etc }); diff --git a/src/test/ui/static/static-extern-type.rs b/src/test/ui/static/static-extern-type.rs new file mode 100644 index 0000000000000..72e2853b9f038 --- /dev/null +++ b/src/test/ui/static/static-extern-type.rs @@ -0,0 +1,37 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +#![feature(extern_types)] + +pub mod a { + extern "C" { + pub type StartFn; + pub static start: StartFn; + } +} + +pub mod b { + #[repr(transparent)] + pub struct TransparentType(::a::StartFn); + extern "C" { + pub static start: TransparentType; + } +} + +pub mod c { + #[repr(C)] + pub struct CType(u32, ::b::TransparentType); + extern "C" { + pub static start: CType; + } +} + +fn main() {} From 5b84550d7c39821704a48b53c8cbe3916ab100b7 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 22 Oct 2018 07:03:53 -0700 Subject: [PATCH 04/33] Keep an obligation for both sized and unsized types --- src/librustc_typeck/check/wfcheck.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec6ca242fa36b..f21296a2a0772 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -340,33 +340,31 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - ty_span: Span, - allow_foreign_ty: bool) { +fn check_item_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool, +) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); - let mut allow_unsized = false; + let mut forbid_unsized = true; if allow_foreign_ty { if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { - allow_unsized = true; + forbid_unsized = false; } } - if !allow_unsized { - fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + if forbid_unsized { fcx.register_bound( item_ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), + traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), ); } From 1c8fb66e8f40451d442de020b58a5da67c5c24b6 Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 22 Oct 2018 20:37:56 +0200 Subject: [PATCH 05/33] Move `BoundTy` to `ty::TyKind` --- src/librustc/ich/impls_ty.rs | 4 ++- src/librustc/infer/canonical/canonicalizer.rs | 21 +++++------- .../infer/canonical/query_response.rs | 2 +- src/librustc/infer/canonical/substitute.rs | 3 +- src/librustc/infer/freshen.rs | 4 +-- src/librustc/traits/coherence.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/query/dropck_outlives.rs | 1 + src/librustc/traits/select.rs | 6 ++-- src/librustc/ty/context.rs | 2 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 5 +-- src/librustc/ty/item_path.rs | 1 + src/librustc/ty/layout.rs | 9 ++++-- src/librustc/ty/mod.rs | 3 +- src/librustc/ty/outlives.rs | 1 + src/librustc/ty/structural_impls.rs | 32 +++++++++++++++---- src/librustc/ty/sty.rs | 30 ++++++++++++++--- src/librustc/ty/subst.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 1 + src/librustc/util/ppaux.rs | 17 ++++++++-- .../debuginfo/type_names.rs | 1 + src/librustc_lint/types.rs | 1 + src/librustc_mir/monomorphize/item.rs | 1 + src/librustc_traits/chalk_context.rs | 1 + src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_traits/lowering/environment.rs | 1 + src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 1 + src/librustdoc/clean/mod.rs | 1 + 33 files changed, 116 insertions(+), 51 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 642eb11006649..3ae8bcdd8b7ca 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -898,6 +898,9 @@ for ty::TyKind<'gcx> Param(param_ty) => { param_ty.hash_stable(hcx, hasher); } + Bound(bound_ty) => { + bound_ty.hash_stable(hcx, hasher); + } Foreign(def_id) => { def_id.hash_stable(hcx, hasher); } @@ -915,7 +918,6 @@ impl_stable_hash_for!(enum ty::InferTy { FreshTy(a), FreshIntTy(a), FreshFloatTy(a), - BoundTy(a), }); impl<'a, 'gcx> HashStable> diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 2b085a3407ccc..2a04a8aed5157 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -283,8 +283,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> bug!("encountered a fresh type during canonicalization") } - ty::Infer(ty::BoundTy(_)) => { - bug!("encountered a canonical type during canonicalization") + ty::Bound(_) => { + bug!("encountered a bound type during canonicalization") } ty::Closure(..) @@ -393,7 +393,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { /// or returns an existing variable if `kind` has already been /// seen. `kind` is expected to be an unbound variable (or /// potentially a free region). - fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy { + fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTyIndex { let Canonicalizer { variables, query_state, @@ -444,19 +444,15 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { }) }; - BoundTy { - level: ty::INNERMOST, - var, - } + var } fn canonical_var_for_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let info = CanonicalVarInfo { kind: CanonicalVarKind::Region, }; - let b = self.canonical_var(info, r.into()); - debug_assert_eq!(ty::INNERMOST, b.level); - self.tcx().mk_region(ty::ReCanonical(b.var)) + let var = self.canonical_var(info, r.into()); + self.tcx().mk_region(ty::ReCanonical(var)) } /// Given a type variable `ty_var` of the given kind, first check @@ -472,9 +468,8 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { let info = CanonicalVarInfo { kind: CanonicalVarKind::Ty(ty_kind), }; - let b = self.canonical_var(info, ty_var.into()); - debug_assert_eq!(ty::INNERMOST, b.level); - self.tcx().mk_infer(ty::InferTy::BoundTy(b)) + let var = self.canonical_var(info, ty_var.into()); + self.tcx().mk_ty(ty::Bound(BoundTy::new(ty::INNERMOST, var))) } } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 38788186eb071..8b798fdaf47d0 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -417,7 +417,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { match result_value.unpack() { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... - if let ty::Infer(ty::InferTy::BoundTy(b)) = result_value.sty { + if let ty::Bound(b) = result_value.sty { // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[b.var] = Some(*original_value); } diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 03441c3dee35e..80a2497bbf613 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -85,8 +85,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { - ty::Infer(ty::InferTy::BoundTy(b)) => { - debug_assert_eq!(ty::INNERMOST, b.level); + ty::Bound(b) => { match self.var_values.var_values[b.var].unpack() { UnpackedKind::Type(ty) => ty, r => bug!("{:?} is a type but value is {:?}", b, r), diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 1647f259db9fb..c12e64b4c2c59 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -171,8 +171,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { t } - ty::Infer(ty::BoundTy(..)) => - bug!("encountered canonical ty during freshening"), + ty::Bound(..) => + bug!("encountered bound ty during freshening"), ty::Generator(..) | ty::Bool | diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 817e9ffcbb55d..71b77909b82a8 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { false } - ty::Infer(..) => match in_crate { + ty::Bound(..) | ty::Infer(..) => match in_crate { InCrate::Local => false, // The inference variable might be unified with a local // type in that remote crate. diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index dc0039926448c..42457dfa1091c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -281,7 +281,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Generator(..) => Some(18), ty::Foreign(..) => Some(19), ty::GeneratorWitness(..) => Some(20), - ty::Infer(..) | ty::Error => None, + ty::Bound(..) | ty::Infer(..) | ty::Error => None, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 8f7b0df8b95aa..62317f074764f 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -252,6 +252,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) + | ty::Bound(..) | ty::Generator(..) => false, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 49f3717935493..b4ce86cdc0293 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2421,7 +2421,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Infer(ty::TyVar(_)) => Ambiguous, ty::UnnormalizedProjection(..) - | ty::Infer(ty::BoundTy(_)) + | ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => { @@ -2506,7 +2506,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } ty::UnnormalizedProjection(..) - | ty::Infer(ty::BoundTy(_)) + | ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => { @@ -2549,7 +2549,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { | ty::Param(..) | ty::Foreign(..) | ty::Projection(..) - | ty::Infer(ty::BoundTy(_)) + | ty::Bound(_) | ty::Infer(ty::TyVar(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c60471c285dcb..88534518089eb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2223,7 +2223,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { sty_debug_print!( self, Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, - Generator, GeneratorWitness, Dynamic, Closure, Tuple, + Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound, Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign); println!("Substs interner: #{}", self.interners.substs.borrow().len()); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index ed6e372fe7637..367f2d19b7313 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -217,7 +217,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::TyVar(_)) => "inferred type".into(), ty::Infer(ty::IntVar(_)) => "integral variable".into(), ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(), - ty::Infer(ty::BoundTy(_)) | + ty::Bound(_) | ty::Infer(ty::FreshTy(_)) => "fresh type".into(), ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index e6aaf8b1bb206..380f95993f8fb 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::Foreign(def_id) => { Some(ForeignSimplifiedType(def_id)) } - ty::Infer(_) | ty::Error => None, + ty::Bound(..) | ty::Infer(_) | ty::Error => None, } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index a7b21688fbeb3..92e08878708f6 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -115,14 +115,15 @@ impl FlagComputation { self.add_substs(&substs.substs); } + &ty::Bound(_) => self.add_flags(TypeFlags::HAS_CANONICAL_VARS), + &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? self.add_flags(TypeFlags::HAS_TY_INFER); match infer { ty::FreshTy(_) | ty::FreshIntTy(_) | - ty::FreshFloatTy(_) | - ty::BoundTy(_) => { + ty::FreshFloatTy(_) => { self.add_flags(TypeFlags::HAS_CANONICAL_VARS); } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 46669f1f9434b..f58294ff4e4bb 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -519,6 +519,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Param(_) | ty::Opaque(..) | ty::Infer(_) | + ty::Bound(..) | ty::Error | ty::GeneratorWitness(..) | ty::Never | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 05d4aeb6ddec4..5500572161735 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1124,9 +1124,14 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } tcx.layout_raw(param_env.and(normalized))? } - ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { + + ty::Bound(..) | + ty::UnnormalizedProjection(..) | + ty::GeneratorWitness(..) | + ty::Infer(_) => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } + ty::Param(_) | ty::Error => { return Err(LayoutError::Unknown(ty)); } @@ -1703,7 +1708,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } - ty::Projection(_) | ty::UnnormalizedProjection(..) | + ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => { bug!("TyLayout::field_type: unexpected type `{}`", this.ty) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index bb9346f2f468d..610262e79d961 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -63,7 +63,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, use hir; -pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST}; +pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundTyIndex, DebruijnIndex, INNERMOST}; pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig}; pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; @@ -2367,6 +2367,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + Bound(..) | Infer(..) => { bug!("unexpected type `{:?}` in sized_constraint_for_ty", ty) diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index b49664b624733..4c820447be234 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -156,6 +156,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::FnDef(..) | // OutlivesFunction (*) ty::FnPtr(_) | // OutlivesFunction (*) ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*) + ty::Bound(..) | ty::Error => { // (*) Bare functions and traits are both binders. In the // RFC, this means we would add the bound regions to the diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 273799bd4bd34..92eca73b6b4a0 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -878,9 +878,19 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::UnnormalizedProjection(data.fold_with(folder)) } ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), - ty::Bool | ty::Char | ty::Str | ty::Int(_) | - ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | - ty::Param(..) | ty::Never | ty::Foreign(..) => return self + + ty::Bool | + ty::Char | + ty::Str | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Error | + ty::Infer(_) | + ty::Param(..) | + ty::Bound(..) | + ty::Never | + ty::Foreign(..) => return self }; if self.sty == sty { @@ -915,9 +925,19 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { data.visit_with(visitor) } ty::Opaque(_, ref substs) => substs.visit_with(visitor), - ty::Bool | ty::Char | ty::Str | ty::Int(_) | - ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | - ty::Param(..) | ty::Never | ty::Foreign(..) => false, + + ty::Bool | + ty::Char | + ty::Str | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Error | + ty::Infer(_) | + ty::Bound(..) | + ty::Param(..) | + ty::Never | + ty::Foreign(..) => false, } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cd9679c876355..9ce02ddf8be07 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -188,6 +188,9 @@ pub enum TyKind<'tcx> { /// A type parameter; for example, `T` in `fn f(x: T) {} Param(ParamTy), + /// Bound type variable, used only when preparing a trait query. + Bound(BoundTy), + /// A type variable used during type checking. Infer(InferTy), @@ -1219,9 +1222,6 @@ pub enum InferTy { FreshTy(u32), FreshIntTy(u32), FreshFloatTy(u32), - - /// Bound type variable, used only when preparing a trait query. - BoundTy(BoundTy), } newtype_index! { @@ -1232,9 +1232,28 @@ newtype_index! { pub struct BoundTy { pub level: DebruijnIndex, pub var: BoundTyIndex, + pub kind: BoundTyKind, } -impl_stable_hash_for!(struct BoundTy { level, var }); +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +pub enum BoundTyKind { + Anon, + Param(InternedString), +} + +impl_stable_hash_for!(struct BoundTy { level, var, kind }); +impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); + +impl BoundTy { + pub fn new(level: DebruijnIndex, var: BoundTyIndex) -> Self { + debug_assert_eq!(ty::INNERMOST, level); + BoundTy { + level, + var, + kind: BoundTyKind::Anon, + } + } +} /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -1865,6 +1884,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { Tuple(..) | Foreign(..) | Param(_) | + Bound(..) | Infer(_) | Error => { vec![] @@ -1930,7 +1950,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ty::Infer(ty::TyVar(_)) => false, - ty::Infer(ty::BoundTy(_)) | + ty::Bound(_) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) => diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 02b5d36ecce6e..87c2c9b6005aa 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -556,7 +556,7 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Infer(ty::BoundTy(ref b)) => cvar == b.var, + ty::Bound(ref b) => cvar == b.var, _ => false, }, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 00a1bfaacd781..0a758285a29b1 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -951,7 +951,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Can refer to a type which may drop. // FIXME(eddyb) check this against a ParamEnv. - ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | + ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 47fbfba87748b..284c595ee2d96 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { match parent_ty.sty { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error | - ty::Foreign(..) => { + ty::Bound(..) | ty::Foreign(..) => { } ty::Array(ty, len) => { push_const(stack, len); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 27747970f76b2..eb97f1177af1b 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -258,6 +258,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::GeneratorWitness(..) | ty::Never | ty::Param(_) | + ty::Bound(..) | ty::Foreign(..) => { // WfScalar, WfParameter, etc } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 709b844526529..da1ebfdf3f5e9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,7 +16,7 @@ use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; -use ty::{Param, RawPtr, Ref, Never, Tuple}; +use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; @@ -984,7 +984,6 @@ define_print! { ty::TyVar(_) => write!(f, "_"), ty::IntVar(_) => write!(f, "{}", "{integer}"), ty::FloatVar(_) => write!(f, "{}", "{float}"), - ty::BoundTy(_) => write!(f, "_"), ty::FreshTy(v) => write!(f, "FreshTy({})", v), ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) @@ -996,7 +995,6 @@ define_print! { ty::TyVar(ref v) => write!(f, "{:?}", v), ty::IntVar(ref v) => write!(f, "{:?}", v), ty::FloatVar(ref v) => write!(f, "{:?}", v), - ty::BoundTy(v) => write!(f, "?{:?}", v.var.index()), ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) @@ -1127,6 +1125,19 @@ define_print! { Infer(infer_ty) => write!(f, "{}", infer_ty), Error => write!(f, "[type error]"), Param(ref param_ty) => write!(f, "{}", param_ty), + Bound(bound_ty) => { + match bound_ty.kind { + ty::BoundTyKind::Anon => { + if bound_ty.level == ty::INNERMOST { + write!(f, "?{}", bound_ty.var.index()) + } else { + write!(f, "?{}_{}", bound_ty.level.index(), bound_ty.var.index()) + } + } + + ty::BoundTyKind::Param(p) => write!(f, "{}", p), + } + } Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]), Dynamic(data, r) => { let r = r.print_to_string(cx); diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index f5abb527e430f..eb5ae81b21840 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ty::Infer(_) | ty::UnnormalizedProjection(..) | ty::Projection(..) | + ty::Bound(..) | ty::Opaque(..) | ty::GeneratorWitness(..) | ty::Param(_) => { diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 5197876f92197..2e19b441d0e39 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -718,6 +718,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Param(..) | ty::Infer(..) | + ty::Bound(..) | ty::Error | ty::Closure(..) | ty::Generator(..) | diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 4c4d56c893838..9d69a5669b1c0 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -382,6 +382,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_type_params(substs, iter::empty(), output); } ty::Error | + ty::Bound(..) | ty::Infer(_) | ty::UnnormalizedProjection(..) | ty::Projection(..) | diff --git a/src/librustc_traits/chalk_context.rs b/src/librustc_traits/chalk_context.rs index 5d6badf120286..bf252053199f8 100644 --- a/src/librustc_traits/chalk_context.rs +++ b/src/librustc_traits/chalk_context.rs @@ -506,6 +506,7 @@ impl context::UnificationOps, ChalkArenas<'tcx>> ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Infer(..) | + ty::Bound(..) | ty::Error => { bug!("unexpected type {:?}", ty) } diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 2ad7ab7c4d927..af64522f18398 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - ty::Infer(..) | ty::Error => { + ty::Bound(..) | ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. Err(NoSolution) diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index c71898f73ecad..052ca37b31371 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -93,6 +93,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Infer(..) | + ty::Bound(..) | ty::Error => { bug!("unexpected type {:?}", ty); } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index e0ee26cba0828..3f0a353124442 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. - ty::Infer(_) => None, + ty::Bound(..) | ty::Infer(_) => None, ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 3e523c0c7f559..b11b034ee13cc 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -338,6 +338,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | + ty::Bound(..) | ty::Infer(..) => { bug!("unexpected type encountered in \ variance inference: {}", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index db605e57735aa..70b90539ac410 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2733,6 +2733,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) + ty::Bound(..) => panic!("Bound"), ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), From cdf55477f59e87bd64f6be3c180ae21d7e117d0f Mon Sep 17 00:00:00 2001 From: scalexm Date: Mon, 22 Oct 2018 22:38:51 +0200 Subject: [PATCH 06/33] Shift both late bound regions and bound types --- src/librustc/infer/outlives/obligations.rs | 2 +- src/librustc/infer/sub.rs | 4 +- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/project.rs | 4 +- src/librustc/traits/query/normalize.rs | 4 +- src/librustc/traits/select.rs | 16 +-- src/librustc/ty/flags.rs | 7 +- src/librustc/ty/fold.rs | 134 ++++++++++++------ src/librustc/ty/instance.rs | 2 +- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/sty.rs | 11 +- src/librustc/ty/subst.rs | 26 ++-- src/librustc/ty/util.rs | 4 +- src/librustc/ty/wf.rs | 14 +- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_driver/test.rs | 12 +- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 6 +- .../implied_outlives_bounds.rs | 2 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/mod.rs | 12 +- src/librustc_typeck/coherence/builtin.rs | 4 +- 25 files changed, 163 insertions(+), 117 deletions(-) diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 332859d4f81db..1cc5676cce1bc 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -305,7 +305,7 @@ where ty, region, origin ); - assert!(!ty.has_escaping_regions()); + assert!(!ty.has_escaping_bound_vars()); let components = self.tcx.outlives_components(ty); self.components_must_outlive(origin, components, region); diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 048810c042722..3b0f9a5e545fd 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -84,8 +84,8 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> // Shouldn't have any LBR here, so we can safely put // this under a binder below without fear of accidental // capture. - assert!(!a.has_escaping_regions()); - assert!(!b.has_escaping_regions()); + assert!(!a.has_escaping_bound_vars()); + assert!(!b.has_escaping_bound_vars()); // can't make progress on `A <: B` if both A and B are // type variables, so record an obligation. We also diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index e6bf02cd73e0d..0ccdb19616a54 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -145,7 +145,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { debug!("normalize_projection_type(projection_ty={:?})", projection_ty); - debug_assert!(!projection_ty.has_escaping_regions()); + debug_assert!(!projection_ty.has_escaping_bound_vars()); // FIXME(#20304) -- cache diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b29ee8f7cdce4..b62724a8aa263 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -366,7 +366,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, let ty = ty.super_fold_with(self); match ty.sty { - ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*) + ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { Reveal::UserFacing => ty, @@ -393,7 +393,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, } } - ty::Projection(ref data) if !data.has_escaping_regions() => { // (*) + ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*) // (*) This is kind of hacky -- we need to be able to // handle normalization within binders because diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 4adb65dc58d91..59b086e35de31 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = ty.super_fold_with(self); match ty.sty { - ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { + ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { @@ -138,7 +138,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx } } - ty::Projection(ref data) if !data.has_escaping_regions() => { + ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*) // (*) This is kind of hacky -- we need to be able to // handle normalization within binders because diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index b4ce86cdc0293..bb1649be1320b 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -587,7 +587,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { debug!("select({:?})", obligation); - debug_assert!(!obligation.predicate.has_escaping_regions()); + debug_assert!(!obligation.predicate.has_escaping_bound_vars()); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); @@ -690,7 +690,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match obligation.predicate { ty::Predicate::Trait(ref t) => { - debug_assert!(!t.has_escaping_regions()); + debug_assert!(!t.has_escaping_bound_vars()); let obligation = obligation.with(t.clone()); self.evaluate_trait_predicate_recursively(previous_stack, obligation) } @@ -722,9 +722,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }, ty::Predicate::TypeOutlives(ref binder) => { - assert!(!binder.has_escaping_regions()); - // Check if the type has higher-ranked regions. - if binder.skip_binder().0.has_escaping_regions() { + assert!(!binder.has_escaping_bound_vars()); + // Check if the type has higher-ranked vars. + if binder.skip_binder().0.has_escaping_bound_vars() { // If so, this obligation is an error (for now). Eventually we should be // able to support additional cases here, like `for<'a> &'a str: 'a`. @@ -740,7 +740,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(EvaluatedToErr) } } else { - // If the type has no late bound regions, then if we assign all + // If the type has no late bound vars, then if we assign all // the inference variables in it to be 'static, then the type // will be 'static itself. // @@ -1199,7 +1199,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})", cache_fresh_trait_pred, stack ); - debug_assert!(!stack.obligation.predicate.has_escaping_regions()); + debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars()); if let Some(c) = self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred) @@ -1765,7 +1765,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { placeholder_map: &infer::PlaceholderMap<'tcx>, snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, ) -> bool { - debug_assert!(!skol_trait_ref.has_escaping_regions()); + debug_assert!(!skol_trait_ref.has_escaping_bound_vars()); if self.infcx .at(&obligation.cause, obligation.param_env) .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 92e08878708f6..d0ea7f653d1e1 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -115,7 +115,10 @@ impl FlagComputation { self.add_substs(&substs.substs); } - &ty::Bound(_) => self.add_flags(TypeFlags::HAS_CANONICAL_VARS), + &ty::Bound(bound_ty) => { + self.add_flags(TypeFlags::HAS_CANONICAL_VARS); + self.add_binder(bound_ty.level); + } &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? @@ -142,7 +145,7 @@ impl FlagComputation { &ty::Projection(ref data) => { // currently we can't normalize projections that // include bound regions, so track those separately. - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); } self.add_flags(TypeFlags::HAS_PROJECTION); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 80dfd263af9af..cb94d7d1083e8 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -67,18 +67,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { /// bound by `binder` or bound by some binder outside of `binder`. /// If `binder` is `ty::INNERMOST`, this indicates whether /// there are any late-bound regions that appear free. - fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder }) + fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }) } /// True if this `self` has any regions that escape `binder` (and /// hence are not bound by it). - fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool { - self.has_regions_bound_at_or_above(binder.shifted_in(1)) + fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { + self.has_vars_bound_at_or_above(binder.shifted_in(1)) } - fn has_escaping_regions(&self) -> bool { - self.has_regions_bound_at_or_above(ty::INNERMOST) + fn has_escaping_bound_vars(&self) -> bool { + self.has_vars_bound_at_or_above(ty::INNERMOST) } fn has_type_flags(&self, flags: TypeFlags) -> bool { @@ -574,7 +574,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_regions_bound_at_or_above(self.current_index) { + if !t.has_vars_bound_at_or_above(self.current_index) { return t; } @@ -603,34 +603,79 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { } /////////////////////////////////////////////////////////////////////////// -// Region shifter +// Shifter // -// Shifts the De Bruijn indices on all escaping bound regions by a +// Shifts the De Bruijn indices on all escaping bound vars by a // fixed amount. Useful in substitution or when otherwise introducing // a binding level that is not intended to capture the existing bound -// regions. See comment on `shift_regions_through_binders` method in +// vars. See comment on `shift_vars_through_binders` method in // `subst.rs` for more details. -pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { - match region { - ty::ReLateBound(debruijn, br) => { - ty::ReLateBound(debruijn.shifted_in(amount), br) +struct Shifter<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + + current_index: ty::DebruijnIndex, + amount: u32, +} + +impl Shifter<'a, 'gcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, amount: u32) -> Self { + Shifter { + tcx, + current_index: ty::INNERMOST, + amount, } - _ => { - region + } +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } + + fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + ty::ReLateBound(debruijn, br) => { + if self.amount == 0 || debruijn < self.current_index { + r + } else { + let shifted = ty::ReLateBound(debruijn.shifted_in(self.amount), br); + self.tcx.mk_region(shifted) + } + } + _ => r + } + } + + fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> { + match ty.sty { + ty::Bound(bound_ty) => { + if self.amount == 0 || bound_ty.level < self.current_index { + ty + } else { + let shifted = ty::BoundTy { + level: bound_ty.level.shifted_in(self.amount), + var: bound_ty.var, + kind: bound_ty.kind, + }; + self.tcx.mk_ty(ty::Bound(shifted)) + } + } + + _ => ty.super_fold_with(self), } } } -pub fn shift_region_ref<'a, 'gcx, 'tcx>( - tcx: TyCtxt<'a, 'gcx, 'tcx>, - region: ty::Region<'tcx>, - amount: u32) - -> ty::Region<'tcx> -{ +pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { match region { - &ty::ReLateBound(debruijn, br) if amount > 0 => { - tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br)) + ty::ReLateBound(debruijn, br) => { + ty::ReLateBound(debruijn.shifted_in(amount), br) } _ => { region @@ -638,20 +683,19 @@ pub fn shift_region_ref<'a, 'gcx, 'tcx>( } } -pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - amount: u32, - value: &T) -> T - where T: TypeFoldable<'tcx> -{ - debug!("shift_regions(value={:?}, amount={})", +pub fn shift_vars<'a, 'gcx, 'tcx, T>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + amount: u32, + value: &T +) -> T where T: TypeFoldable<'tcx> { + debug!("shift_vars(value={:?}, amount={})", value, amount); - value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| { - shift_region_ref(tcx, region, amount) - })) + value.fold_with(&mut Shifter::new(tcx, amount)) } -/// An "escaping region" is a bound region whose binder is not part of `t`. +/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a +/// bound region or a bound type. /// /// So, for example, consider a type like the following, which has two binders: /// @@ -663,24 +707,24 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner /// fn type*, that type has an escaping region: `'a`. /// -/// Note that what I'm calling an "escaping region" is often just called a "free region". However, -/// we already use the term "free region". It refers to the regions that we use to represent bound -/// regions on a fn definition while we are typechecking its body. +/// Note that what I'm calling an "escaping var" is often just called a "free var". However, +/// we already use the term "free var". It refers to the regions or types that we use to represent +/// bound regions or type params on a fn definition while we are typechecking its body. /// /// To clarify, conceptually there is no particular difference between -/// an "escaping" region and a "free" region. However, there is a big +/// an "escaping" var and a "free" var. However, there is a big /// difference in practice. Basically, when "entering" a binding /// level, one is generally required to do some sort of processing to -/// a bound region, such as replacing it with a fresh/placeholder -/// region, or making an entry in the environment to represent the -/// scope to which it is attached, etc. An escaping region represents -/// a bound region for which this processing has not yet been done. -struct HasEscapingRegionsVisitor { +/// a bound var, such as replacing it with a fresh/placeholder +/// var, or making an entry in the environment to represent the +/// scope to which it is attached, etc. An escaping var represents +/// a bound var for which this processing has not yet been done. +struct HasEscapingVarsVisitor { /// Anything bound by `outer_index` or "above" is escaping outer_index: ty::DebruijnIndex, } -impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor { +impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { fn visit_binder>(&mut self, t: &Binder) -> bool { self.outer_index.shift_in(1); let result = t.super_visit_with(self); @@ -693,7 +737,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor { // `outer_index`, that means that `t` contains some content // bound at `outer_index` or above (because // `outer_exclusive_binder` is always 1 higher than the - // content in `t`). Therefore, `t` has some escaping regions. + // content in `t`). Therefore, `t` has some escaping vars. t.outer_exclusive_binder > self.outer_index } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 3d205215d64c6..c2b0ef2aea566 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -145,7 +145,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { impl<'a, 'b, 'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> Instance<'tcx> { - assert!(!substs.has_escaping_regions(), + assert!(!substs.has_escaping_bound_vars(), "substs of instance {:?} not normalized for codegen: {:?}", def_id, substs); Instance { def: InstanceDef::Item(def_id), substs: substs } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 4c820447be234..449730c9d0601 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // we simply fallback to the most restrictive rule, which // requires that `Pi: 'a` for all `i`. ty::Projection(ref data) => { - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { // best case: no escaping regions, so push the // projection and skip the subtree (thus generating no // constraints for Pi). This defers the choice between diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 9ce02ddf8be07..4f2bddfa18b83 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -730,8 +730,8 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { /// or some placeholder type. pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { - // otherwise the escaping regions would be captured by the binder - // debug_assert!(!self_ty.has_escaping_regions()); + // otherwise the escaping vars would be captured by the binder + // debug_assert!(!self_ty.has_escaping_bound_vars()); ty::TraitRef { def_id: self.def_id, @@ -776,7 +776,7 @@ impl Binder { pub fn dummy<'tcx>(value: T) -> Binder where T: TypeFoldable<'tcx> { - debug_assert!(!value.has_escaping_regions()); + debug_assert!(!value.has_escaping_bound_vars()); Binder(value) } @@ -835,7 +835,7 @@ impl Binder { pub fn no_late_bound_regions<'tcx>(self) -> Option where T : TypeFoldable<'tcx> { - if self.skip_binder().has_escaping_regions() { + if self.skip_binder().has_escaping_bound_vars() { None } else { Some(self.skip_binder().clone()) @@ -1246,7 +1246,6 @@ impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); impl BoundTy { pub fn new(level: DebruijnIndex, var: BoundTyIndex) -> Self { - debug_assert_eq!(ty::INNERMOST, level); BoundTy { level, var, @@ -1283,7 +1282,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { -> ty::ProjectionPredicate<'tcx> { // otherwise the escaping regions would be captured by the binders - debug_assert!(!self_ty.has_escaping_regions()); + debug_assert!(!self_ty.has_escaping_bound_vars()); ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 87c2c9b6005aa..9e85cfe7a12e7 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -355,7 +355,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T { span, root_ty: None, ty_stack_depth: 0, - region_binders_passed: 0 }; + binders_passed: 0 }; (*self).fold_with(&mut folder) } } @@ -377,16 +377,16 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { ty_stack_depth: usize, // Number of region binders we have passed through while doing the substitution - region_binders_passed: u32, + binders_passed: u32, } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { - self.region_binders_passed += 1; + self.binders_passed += 1; let t = t.super_fold_with(self); - self.region_binders_passed -= 1; + self.binders_passed -= 1; t } @@ -471,7 +471,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { } }; - self.shift_regions_through_binders(ty) + self.shift_vars_through_binders(ty) } /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs @@ -516,25 +516,25 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the /// first case we do not increase the Debruijn index and in the second case we do. The reason /// is that only in the second case have we passed through a fn binder. - fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("shift_regions(ty={:?}, region_binders_passed={:?}, has_escaping_regions={:?})", - ty, self.region_binders_passed, ty.has_escaping_regions()); + fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> { + debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", + ty, self.binders_passed, ty.has_escaping_bound_vars()); - if self.region_binders_passed == 0 || !ty.has_escaping_regions() { + if self.binders_passed == 0 || !ty.has_escaping_bound_vars() { return ty; } - let result = ty::fold::shift_regions(self.tcx(), self.region_binders_passed, &ty); - debug!("shift_regions: shifted result = {:?}", result); + let result = ty::fold::shift_vars(self.tcx(), self.binders_passed, &ty); + debug!("shift_vars: shifted result = {:?}", result); result } fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> { - if self.region_binders_passed == 0 || !region.has_escaping_regions() { + if self.binders_passed == 0 || !region.has_escaping_bound_vars() { return region; } - self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed)) + self.tcx().mk_region(ty::fold::shift_region(*region, self.binders_passed)) } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0a758285a29b1..1b1bbfd4deb8b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -363,7 +363,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { erased_self_ty, predicates); - assert!(!erased_self_ty.has_escaping_regions()); + assert!(!erased_self_ty.has_escaping_bound_vars()); traits::elaborate_predicates(self, predicates) .filter_map(|predicate| { @@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // construct such an object, but this seems // correct even if that code changes). let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder(); - if t == &erased_self_ty && !r.has_escaping_regions() { + if t == &erased_self_ty && !r.has_escaping_bound_vars() { Some(*r) } else { None diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index eb97f1177af1b..1336eac63f880 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -158,7 +158,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let infcx = &mut self.infcx; let param_env = self.param_env; self.out.iter() - .inspect(|pred| assert!(!pred.has_escaping_regions())) + .inspect(|pred| assert!(!pred.has_escaping_bound_vars())) .flat_map(|pred| { let mut selcx = traits::SelectionContext::new(infcx); let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred); @@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.out.extend( trait_ref.substs.types() - .filter(|ty| !ty.has_escaping_regions()) + .filter(|ty| !ty.has_escaping_bound_vars()) .map(|ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)))); @@ -205,7 +205,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let trait_ref = data.trait_ref(self.infcx.tcx); self.compute_trait_ref(&trait_ref, Elaborate::None); - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { let predicate = trait_ref.to_predicate(); let cause = self.cause(traits::ProjectionWf(data)); self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); @@ -229,7 +229,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { } fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { - if !subty.has_escaping_regions() { + if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); let trait_ref = ty::TraitRef { def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), @@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { ty::Ref(r, rty, _) => { // WfReference - if !r.has_escaping_regions() && !rty.has_escaping_regions() { + if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); self.out.push( traits::Obligation::new( @@ -451,7 +451,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { .map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred)) - .filter(|pred| !pred.has_escaping_regions()) + .filter(|pred| !pred.has_escaping_bound_vars()) .collect() } @@ -490,7 +490,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // Note: in fact we only permit builtin traits, not `Bar<'d>`, I // am looking forward to the future here. - if !data.has_escaping_regions() { + if !data.has_escaping_bound_vars() { let implicit_bounds = object_region_bounds(self.infcx.tcx, data); diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 4b4ccb3b600b3..1b5f4ac5cf20f 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -44,7 +44,7 @@ pub fn get_fn( debug!("get_fn(instance={:?})", instance); assert!(!instance.substs.needs_infer()); - assert!(!instance.substs.has_escaping_regions()); + assert!(!instance.substs.has_escaping_bound_vars()); assert!(!instance.substs.has_param_types()); let fn_ty = instance.ty(cx.tcx); diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 03ded64e64235..b01d7e3a776f7 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -285,7 +285,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { debug!("llvm_type({:#?})", self); - assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty); + assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty); // Make sure lifetimes are erased, to avoid generating distinct LLVM // types for Rust types that only differ in the choice of lifetimes. diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index f18f40bf7a144..28b7c610a91c0 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -616,22 +616,22 @@ fn escaping() { // Theta = [A -> &'a foo] env.create_simple_region_hierarchy(); - assert!(!env.t_nil().has_escaping_regions()); + assert!(!env.t_nil().has_escaping_bound_vars()); let t_rptr_free1 = env.t_rptr_free(1); - assert!(!t_rptr_free1.has_escaping_regions()); + assert!(!t_rptr_free1.has_escaping_bound_vars()); let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1()); - assert!(t_rptr_bound1.has_escaping_regions()); + assert!(t_rptr_bound1.has_escaping_bound_vars()); let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2()); - assert!(t_rptr_bound2.has_escaping_regions()); + assert!(t_rptr_bound2.has_escaping_bound_vars()); // t_fn = fn(A) let t_param = env.t_param(0); - assert!(!t_param.has_escaping_regions()); + assert!(!t_param.has_escaping_bound_vars()); let t_fn = env.t_fn(&[t_param], env.t_nil()); - assert!(!t_fn.has_escaping_regions()); + assert!(!t_fn.has_escaping_bound_vars()); }) } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6db107344747e..c0f8e936f09e2 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -359,7 +359,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_escaping_regions() || ty.references_error() { + if ty.has_escaping_bound_vars() || ty.references_error() { span_mirbug_and_err!(self, parent, "bad type {:?}", ty) } else { ty diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 6b60b5340eee7..27a2a0481736c 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -903,12 +903,12 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_ty: Ty<'tcx>, impl_ty: Ty<'tcx>, output: &mut Vec>) { - assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() && - !impl_ty.needs_subst() && !impl_ty.has_escaping_regions()); + assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_bound_vars() && + !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars()); if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty { let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty); - assert!(!poly_trait_ref.has_escaping_regions()); + assert!(!poly_trait_ref.has_escaping_bound_vars()); // Walk all methods of the trait, including those of its supertraits let methods = tcx.vtable_methods(poly_trait_ref); diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index ad0a54e392f58..228125b11b66a 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -108,7 +108,7 @@ fn compute_implied_outlives_bounds<'tcx>( // From the full set of obligations, just filter down to the // region relationships. implied_bounds.extend(obligations.into_iter().flat_map(|obligation| { - assert!(!obligation.has_escaping_regions()); + assert!(!obligation.has_escaping_bound_vars()); match obligation.predicate { ty::Predicate::Trait(..) | ty::Predicate::Subtype(..) | diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 3f4d187813d5d..5a758ab642bac 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -458,7 +458,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Create a `PolyFnSig`. Note the oddity that late bound // regions appearing free in `expected_sig` are now bound up // in this binder we are creating. - assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST)); + assert!(!expected_sig.sig.has_vars_bound_above(ty::INNERMOST)); let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig( expected_sig.sig.inputs().iter().cloned(), expected_sig.sig.output(), diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 04c32fa88271a..11448750618e2 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { value } }; - assert!(!bounds.has_escaping_regions()); + assert!(!bounds.has_escaping_bound_vars()); let cause = traits::ObligationCause::misc(span, self.body_id); obligations.extend(traits::predicates_for_generics(cause.clone(), diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index f4538dbd25e2f..13969b7eafe9b 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1373,7 +1373,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn_sig, substs); - assert!(!substs.has_escaping_regions()); + assert!(!substs.has_escaping_bound_vars()); // It is possible for type parameters or early-bound lifetimes // to appear in the signature of `self`. The substitutions we diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1c562859bb48d..917d8e0231fcf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -653,8 +653,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) { debug!("register_predicate({:?})", obligation); - if obligation.has_escaping_regions() { - span_bug!(obligation.cause.span, "escaping regions in predicate {:?}", + if obligation.has_escaping_bound_vars() { + span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation); } self.fulfillment_cx @@ -1928,7 +1928,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { } fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.has_escaping_regions() { + if ty.has_escaping_bound_vars() { ty // FIXME: normalization and escaping regions } else { self.normalize_associated_types_in(span, &ty) @@ -2431,7 +2431,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { cause: traits::ObligationCause<'tcx>, predicates: &ty::InstantiatedPredicates<'tcx>) { - assert!(!predicates.has_escaping_regions()); + assert!(!predicates.has_escaping_bound_vars()); debug!("add_obligations_for_parameters(predicates={:?})", predicates); @@ -5206,8 +5206,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }, ); - assert!(!substs.has_escaping_regions()); - assert!(!ty.has_escaping_regions()); + assert!(!substs.has_escaping_bound_vars()); + assert!(!ty.has_escaping_bound_vars()); // Write the "user substs" down first thing for later. let hir_id = self.tcx.hir.node_to_hir_id(node_id); diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c54d9e4b47578..f9ca9d8caf7cc 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -98,7 +98,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did: let span = tcx.hir.span(impl_node_id); let param_env = tcx.param_env(impl_did); - assert!(!self_type.has_escaping_regions()); + assert!(!self_type.has_escaping_bound_vars()); debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type); @@ -187,7 +187,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, let span = gcx.hir.span(impl_node_id); let param_env = gcx.param_env(impl_did); - assert!(!source.has_escaping_regions()); + assert!(!source.has_escaping_bound_vars()); let err_info = CoerceUnsizedInfo { custom_kind: None }; From ab820ad71993de8cbdc4ac32590d2eab65803c71 Mon Sep 17 00:00:00 2001 From: scalexm Date: Tue, 23 Oct 2018 13:42:23 +0200 Subject: [PATCH 07/33] Rename `BoundTyIndex` to `BoundVar` --- src/librustc/ich/impls_ty.rs | 2 +- src/librustc/infer/canonical/canonicalizer.rs | 14 +++++++------- src/librustc/infer/canonical/mod.rs | 10 +++++----- src/librustc/infer/canonical/query_response.rs | 14 +++++++------- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 8 ++++---- src/librustc/ty/subst.rs | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 3ae8bcdd8b7ca..9c612eef5e7b0 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -147,7 +147,7 @@ impl<'a> HashStable> for ty::RegionVid { } } -impl<'gcx> HashStable> for ty::BoundTyIndex { +impl<'gcx> HashStable> for ty::BoundVar { #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 2a04a8aed5157..8c30130fef22c 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -23,7 +23,7 @@ use infer::InferCtxt; use std::sync::atomic::Ordering; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::Kind; -use ty::{self, BoundTy, BoundTyIndex, Lift, List, Ty, TyCtxt, TypeFlags}; +use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -225,7 +225,7 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { query_state: &'cx mut OriginalQueryValues<'tcx>, // Note that indices is only used once `var_values` is big enough to be // heap-allocated. - indices: FxHashMap, BoundTyIndex>, + indices: FxHashMap, BoundVar>, canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode, needs_canonical_flags: TypeFlags, } @@ -393,7 +393,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { /// or returns an existing variable if `kind` has already been /// seen. `kind` is expected to be an unbound variable (or /// potentially a free region). - fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTyIndex { + fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundVar { let Canonicalizer { variables, query_state, @@ -413,7 +413,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { // direct linear search of `var_values`. if let Some(idx) = var_values.iter().position(|&k| k == kind) { // `kind` is already present in `var_values`. - BoundTyIndex::new(idx) + BoundVar::new(idx) } else { // `kind` isn't present in `var_values`. Append it. Likewise // for `info` and `variables`. @@ -428,11 +428,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { *indices = var_values .iter() .enumerate() - .map(|(i, &kind)| (kind, BoundTyIndex::new(i))) + .map(|(i, &kind)| (kind, BoundVar::new(i))) .collect(); } // The cv is the index of the appended element. - BoundTyIndex::new(var_values.len() - 1) + BoundVar::new(var_values.len() - 1) } } else { // `var_values` is large. Do a hashmap search via `indices`. @@ -440,7 +440,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { variables.push(info); var_values.push(kind); assert_eq!(variables.len(), var_values.len()); - BoundTyIndex::new(variables.len() - 1) + BoundVar::new(variables.len() - 1) }) }; diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index e3bd407d17a90..825e6f8fffbed 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -40,7 +40,7 @@ use std::ops::Index; use syntax::source_map::Span; use ty::fold::TypeFoldable; use ty::subst::Kind; -use ty::{self, BoundTyIndex, Lift, Region, List, TyCtxt}; +use ty::{self, BoundVar, Lift, Region, List, TyCtxt}; mod canonicalizer; @@ -72,7 +72,7 @@ impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {} /// canonicalized query response. #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] pub struct CanonicalVarValues<'tcx> { - pub var_values: IndexVec>, + pub var_values: IndexVec>, } /// When we canonicalize a value to form a query, we wind up replacing @@ -264,7 +264,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { span: Span, variables: &List, ) -> CanonicalVarValues<'tcx> { - let var_values: IndexVec> = variables + let var_values: IndexVec> = variables .iter() .map(|info| self.fresh_inference_var_for_canonical_var(span, *info)) .collect(); @@ -367,10 +367,10 @@ BraceStructLiftImpl! { } where R: Lift<'tcx> } -impl<'tcx> Index for CanonicalVarValues<'tcx> { +impl<'tcx> Index for CanonicalVarValues<'tcx> { type Output = Kind<'tcx>; - fn index(&self, value: BoundTyIndex) -> &Kind<'tcx> { + fn index(&self, value: BoundVar) -> &Kind<'tcx> { &self.var_values[value] } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 8b798fdaf47d0..de01d467b0716 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -35,7 +35,7 @@ use traits::{FulfillmentContext, TraitEngine}; use traits::{Obligation, ObligationCause, PredicateObligation}; use ty::fold::TypeFoldable; use ty::subst::{Kind, UnpackedKind}; -use ty::{self, BoundTyIndex, Lift, Ty, TyCtxt}; +use ty::{self, BoundVar, Lift, Ty, TyCtxt}; impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> { /// The "main method" for a canonicalized trait query. Given the @@ -273,7 +273,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { for (index, original_value) in original_values.var_values.iter().enumerate() { // ...with the value `v_r` of that variable from the query. let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| { - &v.var_values[BoundTyIndex::new(index)] + &v.var_values[BoundVar::new(index)] }); match (original_value.unpack(), result_value.unpack()) { (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => { @@ -408,7 +408,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // is directly equal to one of the canonical variables in the // result, then we can type the corresponding value from the // input. See the example above. - let mut opt_values: IndexVec>> = + let mut opt_values: IndexVec>> = IndexVec::from_elem_n(None, query_response.variables.len()); // In terms of our example above, we are iterating over pairs like: @@ -440,7 +440,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { .variables .iter() .enumerate() - .map(|(index, info)| opt_values[BoundTyIndex::new(index)].unwrap_or_else(|| + .map(|(index, info)| opt_values[BoundVar::new(index)].unwrap_or_else(|| self.fresh_inference_var_for_canonical_var(cause.span, *info) )) .collect(), @@ -470,7 +470,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // canonical variable; this is taken from // `query_response.var_values` after applying the substitution // `result_subst`. - let substituted_query_response = |index: BoundTyIndex| -> Kind<'tcx> { + let substituted_query_response = |index: BoundVar| -> Kind<'tcx> { query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index]) }; @@ -526,12 +526,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, variables1: &OriginalQueryValues<'tcx>, - variables2: impl Fn(BoundTyIndex) -> Kind<'tcx>, + variables2: impl Fn(BoundVar) -> Kind<'tcx>, ) -> InferResult<'tcx, ()> { self.commit_if_ok(|_| { let mut obligations = vec![]; for (index, value1) in variables1.var_values.iter().enumerate() { - let value2 = variables2(BoundTyIndex::new(index)); + let value2 = variables2(BoundVar::new(index)); match (value1.unpack(), value2.unpack()) { (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 610262e79d961..f6ba9f0c2b633 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -63,7 +63,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, use hir; -pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundTyIndex, DebruijnIndex, INNERMOST}; +pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST}; pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig}; pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut}; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4f2bddfa18b83..23feceac4dd66 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1171,7 +1171,7 @@ pub enum RegionKind { ReClosureBound(RegionVid), /// Canonicalized region, used only when preparing a trait query. - ReCanonical(BoundTyIndex), + ReCanonical(BoundVar), } impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {} @@ -1225,13 +1225,13 @@ pub enum InferTy { } newtype_index! { - pub struct BoundTyIndex { .. } + pub struct BoundVar { .. } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BoundTy { pub level: DebruijnIndex, - pub var: BoundTyIndex, + pub var: BoundVar, pub kind: BoundTyKind, } @@ -1245,7 +1245,7 @@ impl_stable_hash_for!(struct BoundTy { level, var, kind }); impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); impl BoundTy { - pub fn new(level: DebruijnIndex, var: BoundTyIndex) -> Self { + pub fn new(level: DebruijnIndex, var: BoundVar) -> Self { BoundTy { level, var, diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 9e85cfe7a12e7..fd26b263efb0f 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -12,7 +12,7 @@ use hir::def_id::DefId; use infer::canonical::Canonical; -use ty::{self, BoundTyIndex, Lift, List, Ty, TyCtxt}; +use ty::{self, BoundVar, Lift, List, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{self, Encodable, Encoder, Decodable, Decoder}; @@ -553,7 +553,7 @@ impl CanonicalUserSubsts<'tcx> { return false; } - self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| { + self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { ty::Bound(ref b) => cvar == b.var, From 9049c8521c3aad17b824232e85d6846c57a5658c Mon Sep 17 00:00:00 2001 From: scalexm Date: Tue, 23 Oct 2018 16:28:53 +0200 Subject: [PATCH 08/33] Rename `BoundTy` field `level` -> `index` --- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/fold.rs | 4 ++-- src/librustc/ty/sty.rs | 8 ++++---- src/librustc/util/ppaux.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index d0ea7f653d1e1..6c1070f74e0d5 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -117,7 +117,7 @@ impl FlagComputation { &ty::Bound(bound_ty) => { self.add_flags(TypeFlags::HAS_CANONICAL_VARS); - self.add_binder(bound_ty.level); + self.add_binder(bound_ty.index); } &ty::Infer(infer) => { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index cb94d7d1083e8..87ff5d2a36d89 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -655,11 +655,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> { match ty.sty { ty::Bound(bound_ty) => { - if self.amount == 0 || bound_ty.level < self.current_index { + if self.amount == 0 || bound_ty.index < self.current_index { ty } else { let shifted = ty::BoundTy { - level: bound_ty.level.shifted_in(self.amount), + index: bound_ty.index.shifted_in(self.amount), var: bound_ty.var, kind: bound_ty.kind, }; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 23feceac4dd66..e57e7d759d517 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1230,7 +1230,7 @@ newtype_index! { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct BoundTy { - pub level: DebruijnIndex, + pub index: DebruijnIndex, pub var: BoundVar, pub kind: BoundTyKind, } @@ -1241,13 +1241,13 @@ pub enum BoundTyKind { Param(InternedString), } -impl_stable_hash_for!(struct BoundTy { level, var, kind }); +impl_stable_hash_for!(struct BoundTy { index, var, kind }); impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) }); impl BoundTy { - pub fn new(level: DebruijnIndex, var: BoundVar) -> Self { + pub fn new(index: DebruijnIndex, var: BoundVar) -> Self { BoundTy { - level, + index, var, kind: BoundTyKind::Anon, } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index da1ebfdf3f5e9..4a5d956ed4e8e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1128,10 +1128,10 @@ define_print! { Bound(bound_ty) => { match bound_ty.kind { ty::BoundTyKind::Anon => { - if bound_ty.level == ty::INNERMOST { + if bound_ty.index == ty::INNERMOST { write!(f, "?{}", bound_ty.var.index()) } else { - write!(f, "?{}_{}", bound_ty.level.index(), bound_ty.var.index()) + write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index()) } } From 8642a23a561a254add952d839cf862ba3a0ac4a2 Mon Sep 17 00:00:00 2001 From: scalexm Date: Tue, 23 Oct 2018 19:47:53 +0200 Subject: [PATCH 09/33] Adjust bound tys indices in canonicalization --- src/librustc/infer/canonical/canonicalizer.rs | 31 +++++++++++++++---- .../infer/canonical/query_response.rs | 1 + src/librustc/infer/canonical/substitute.rs | 30 +++++++++++++++--- src/librustc/ty/subst.rs | 5 ++- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 8c30130fef22c..8d6ebcf21b6a1 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -228,6 +228,8 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { indices: FxHashMap, BoundVar>, canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode, needs_canonical_flags: TypeFlags, + + binder_index: ty::DebruijnIndex, } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> { @@ -235,11 +237,23 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> self.tcx } + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T: TypeFoldable<'tcx> + { + self.binder_index.shift_in(1); + let t = t.super_fold_with(self); + self.binder_index.shift_out(1); + t + } + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(..) => { - // leave bound regions alone - r + ty::ReLateBound(index, ..) => { + if index >= self.binder_index { + bug!("escaping late bound region during canonicalization") + } else { + r + } } ty::ReVar(vid) => { @@ -283,8 +297,12 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> bug!("encountered a fresh type during canonicalization") } - ty::Bound(_) => { - bug!("encountered a bound type during canonicalization") + ty::Bound(bound_ty) => { + if bound_ty.index >= self.binder_index { + bug!("escaping bound type during canonicalization") + } else { + t + } } ty::Closure(..) @@ -367,6 +385,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { variables: SmallVec::new(), query_state, indices: FxHashMap::default(), + binder_index: ty::INNERMOST, }; let out_value = value.fold_with(&mut canonicalizer); @@ -469,7 +488,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { kind: CanonicalVarKind::Ty(ty_kind), }; let var = self.canonical_var(info, ty_var.into()); - self.tcx().mk_ty(ty::Bound(BoundTy::new(ty::INNERMOST, var))) + self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var))) } } } diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index de01d467b0716..89986bbf90dbb 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -418,6 +418,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... if let ty::Bound(b) = result_value.sty { + assert_eq!(b.index, ty::INNERMOST); // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[b.var] = Some(*original_value); } diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 80a2497bbf613..5b2e758d81673 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -69,13 +69,18 @@ where } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { value.clone() } else { - value.fold_with(&mut CanonicalVarValuesSubst { tcx, var_values }) + value.fold_with(&mut CanonicalVarValuesSubst { + tcx, + var_values, + binder_index: ty::INNERMOST, + }) } } struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, var_values: &'cx CanonicalVarValues<'tcx>, + binder_index: ty::DebruijnIndex, } impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> { @@ -83,12 +88,29 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g self.tcx } + fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder + where T: TypeFoldable<'tcx> + { + self.binder_index.shift_in(1); + let t = t.super_fold_with(self); + self.binder_index.shift_out(1); + t + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match t.sty { ty::Bound(b) => { - match self.var_values.var_values[b.var].unpack() { - UnpackedKind::Type(ty) => ty, - r => bug!("{:?} is a type but value is {:?}", b, r), + if b.index == self.binder_index { + match self.var_values.var_values[b.var].unpack() { + UnpackedKind::Type(ty) => ty::fold::shift_vars( + self.tcx, + self.binder_index.index() as u32, + &ty + ), + r => bug!("{:?} is a type but value is {:?}", b, r), + } + } else { + t } } _ => { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index fd26b263efb0f..6bdbeb8f604fc 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -556,7 +556,10 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(ref b) => cvar == b.var, + ty::Bound(ref b) => { + assert_eq!(b.index, ty::INNERMOST); + cvar == b.var + } _ => false, }, From e76fffc754482b5f0f8f9a3985210431ccb01e8f Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 24 Oct 2018 10:29:42 +0200 Subject: [PATCH 10/33] Remove `ReCanonical` in favor of `ReLateBound` --- src/librustc/ich/impls_ty.rs | 3 -- src/librustc/infer/canonical/canonicalizer.rs | 16 +++---- src/librustc/infer/canonical/mod.rs | 2 +- .../infer/canonical/query_response.rs | 48 +++++++++++-------- src/librustc/infer/canonical/substitute.rs | 31 ++++++++---- src/librustc/infer/combine.rs | 1 - src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/infer/freshen.rs | 1 - .../infer/lexical_region_resolve/mod.rs | 4 +- src/librustc/infer/region_constraints/mod.rs | 4 -- src/librustc/ty/flags.rs | 2 - src/librustc/ty/fold.rs | 14 ++++-- src/librustc/ty/mod.rs | 7 +-- src/librustc/ty/sty.rs | 30 ++++++------ src/librustc/ty/subst.rs | 17 ++++--- src/librustc/util/ppaux.rs | 7 --- src/librustc_borrowck/borrowck/check_loans.rs | 1 - .../borrowck/gather_loans/mod.rs | 1 - .../error_reporting/region_name.rs | 3 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/outlives/utils.rs | 1 - src/librustc_typeck/variance/constraints.rs | 1 - src/librustdoc/clean/mod.rs | 1 - 23 files changed, 98 insertions(+), 101 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9c612eef5e7b0..e0ed4219a4834 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -100,9 +100,6 @@ for ty::RegionKind { ty::ReEmpty => { // No variant fields to hash for these ... } - ty::ReCanonical(c) => { - c.hash_stable(hcx, hasher); - } ty::ReLateBound(db, ty::BrAnon(i)) => { db.hash_stable(hcx, hasher); i.hash_stable(hcx, hasher); diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 8d6ebcf21b6a1..323057415afdd 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -277,8 +277,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::ReEmpty | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r), - ty::ReClosureBound(..) | ty::ReCanonical(_) => { - bug!("canonical region encountered during canonicalization") + ty::ReClosureBound(..) => { + bug!("closure bound region encountered during canonicalization") } } } @@ -353,12 +353,6 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { where V: TypeFoldable<'tcx> + Lift<'gcx>, { - debug_assert!( - !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS), - "canonicalizing a canonical value: {:?}", - value, - ); - let needs_canonical_flags = if canonicalize_region_mode.any() { TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX } else { @@ -471,7 +465,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { kind: CanonicalVarKind::Region, }; let var = self.canonical_var(info, r.into()); - self.tcx().mk_region(ty::ReCanonical(var)) + let region = ty::ReLateBound( + self.binder_index, + ty::BoundRegion::BrAnon(var.index() as u32) + ); + self.tcx().mk_region(region) } /// Given a type variable `ty_var` of the given kind, first check diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 825e6f8fffbed..696220691e141 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -20,7 +20,7 @@ //! - a map M (of type `CanonicalVarValues`) from those canonical //! variables back to the original. //! -//! We can then do queries using T2. These will give back constriants +//! We can then do queries using T2. These will give back constraints //! on the canonical variables which can be translated, using the map //! M, into constraints in our source context. This process of //! translating the results back is done by the diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 89986bbf90dbb..c365e8614eddb 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -308,11 +308,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // ...also include the other query region constraints from the query. output_query_region_constraints.extend( query_response.value.region_constraints.iter().filter_map(|r_c| { - let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below - let k1 = substitute_value(self.tcx, &result_subst, &k1); - let r2 = substitute_value(self.tcx, &result_subst, &r2); - if k1 != r2.into() { - Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2))) + let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below + let k1 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*k1)); + let r2 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*r2)); + if k1 != r2.map_bound(|bound| bound.into()) { + let predicate = ty::OutlivesPredicate(*k1.skip_binder(), *r2.skip_binder()); + Some(ty::Binder::bind(predicate)) } else { None } @@ -418,16 +419,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... if let ty::Bound(b) = result_value.sty { + // ...in which case we would set `canonical_vars[0]` to `Some(?U)`. + + // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(b.index, ty::INNERMOST); - // in which case we would set `canonical_vars[0]` to `Some(?U)`. opt_values[b.var] = Some(*original_value); } } UnpackedKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let &ty::RegionKind::ReCanonical(index) = result_value { - // in which case we would set `canonical_vars[0]` to `Some('static)`. - opt_values[index] = Some(*original_value); + if let &ty::RegionKind::ReLateBound(index, br) = result_value { + // ... in which case we would set `canonical_vars[0]` to `Some('static)`. + + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(index, ty::INNERMOST); + opt_values[br.as_bound_var()] = Some(*original_value); } } } @@ -499,21 +505,23 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { .iter() .map(move |constraint| { let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below - let k1 = substitute_value(self.tcx, result_subst, k1); - let r2 = substitute_value(self.tcx, result_subst, r2); + let k1 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*k1)); + let r2 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*r2)); Obligation::new( cause.clone(), param_env, - match k1.unpack() { + match k1.skip_binder().unpack() { UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( - ty::Binder::dummy( - ty::OutlivesPredicate(r1, r2) - )), + ty::Binder::bind( + ty::OutlivesPredicate(r1, r2.skip_binder()) + ) + ), UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( - ty::Binder::dummy(ty::OutlivesPredicate( - t1, r2 - ))) + ty::Binder::bind( + ty::OutlivesPredicate(t1, r2.skip_binder()) + ) + ), } ) }) @@ -595,11 +603,11 @@ pub fn make_query_outlives<'tcx>( } Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), }) - .map(ty::Binder::dummy) // no bound regions in the code above + .map(ty::Binder::dummy) // no bound vars in the code above .chain( outlives_obligations .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) - .map(ty::Binder::dummy), // no bound regions in the code above + .map(ty::Binder::dummy) // no bound vars in the code above ) .collect(); diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 5b2e758d81673..7839c8922660a 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -19,7 +19,7 @@ use infer::canonical::{Canonical, CanonicalVarValues}; use ty::fold::{TypeFoldable, TypeFolder}; use ty::subst::UnpackedKind; -use ty::{self, Ty, TyCtxt, TypeFlags}; +use ty::{self, Ty, TyCtxt}; impl<'tcx, V> Canonical<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value @@ -64,9 +64,9 @@ where T: TypeFoldable<'tcx>, { if var_values.var_values.is_empty() { - debug_assert!(!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS)); value.clone() - } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { + } else if !value.has_escaping_bound_vars() { + // There are no bound vars to substitute. value.clone() } else { value.fold_with(&mut CanonicalVarValuesSubst { @@ -104,8 +104,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g match self.var_values.var_values[b.var].unpack() { UnpackedKind::Type(ty) => ty::fold::shift_vars( self.tcx, - self.binder_index.index() as u32, - &ty + &ty, + self.binder_index.index() as u32 ), r => bug!("{:?} is a type but value is {:?}", b, r), } @@ -114,7 +114,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g } } _ => { - if !t.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) { + if !t.has_vars_bound_at_or_above(self.binder_index) { + // Nothing more to substitute. t } else { t.super_fold_with(self) @@ -125,10 +126,20 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match r { - ty::RegionKind::ReCanonical(c) => match self.var_values.var_values[*c].unpack() { - UnpackedKind::Lifetime(l) => l, - r => bug!("{:?} is a region but value is {:?}", c, r), - }, + ty::RegionKind::ReLateBound(index, br) => { + if *index == self.binder_index { + match self.var_values.var_values[br.as_bound_var()].unpack() { + UnpackedKind::Lifetime(l) => ty::fold::shift_region( + self.tcx, + l, + self.binder_index.index() as u32, + ), + r => bug!("{:?} is a region but value is {:?}", br, r), + } + } else { + r + } + } _ => r.super_fold_with(self), } } diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index de8f57ee79666..f2a4f88be5423 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -477,7 +477,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } } - ty::ReCanonical(..) | ty::ReClosureBound(..) => { span_bug!( self.span, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 8b4669c89fe83..d457cda86c0af 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -152,7 +152,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // We shouldn't encounter an error message with ReClosureBound. - ty::ReCanonical(..) | ty::ReClosureBound(..) => { + ty::ReClosureBound(..) => { bug!("encountered unexpected ReClosureBound: {:?}", region,); } }; diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index c12e64b4c2c59..b53444992fa21 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -114,7 +114,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { self.tcx().types.re_erased } - ty::ReCanonical(..) | ty::ReClosureBound(..) => { bug!( "encountered unexpected region: {:?}", diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 8f28e9a320df2..75f503d3bcfb4 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -260,9 +260,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { let tcx = self.tcx(); match (a, b) { - (&ty::ReCanonical(..), _) - | (_, &ty::ReCanonical(..)) - | (&ty::ReClosureBound(..), _) + (&ty::ReClosureBound(..), _) | (_, &ty::ReClosureBound(..)) | (&ReLateBound(..), _) | (_, &ReLateBound(..)) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 96278e5140c8a..a0eedc0a2b529 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -833,10 +833,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { ty::RePlaceholder(placeholder) => placeholder.universe, ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid), ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), - ty::ReCanonical(..) => bug!( - "region_universe(): encountered canonical region {:?}", - region - ), } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 6c1070f74e0d5..0764f363250dd 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -116,7 +116,6 @@ impl FlagComputation { } &ty::Bound(bound_ty) => { - self.add_flags(TypeFlags::HAS_CANONICAL_VARS); self.add_binder(bound_ty.index); } @@ -127,7 +126,6 @@ impl FlagComputation { ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { - self.add_flags(TypeFlags::HAS_CANONICAL_VARS); } ty::TyVar(_) | diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 87ff5d2a36d89..31542582f9499 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -672,10 +672,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> { } } -pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { +pub fn shift_region<'a, 'gcx, 'tcx>( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + region: ty::Region<'tcx>, + amount: u32 +) -> ty::Region<'tcx> { match region { - ty::ReLateBound(debruijn, br) => { - ty::ReLateBound(debruijn.shifted_in(amount), br) + ty::ReLateBound(debruijn, br) if amount > 0 => { + tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br)) } _ => { region @@ -685,8 +689,8 @@ pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind { pub fn shift_vars<'a, 'gcx, 'tcx, T>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - amount: u32, - value: &T + value: &T, + amount: u32 ) -> T where T: TypeFoldable<'tcx> { debug!("shift_vars(value={:?}, amount={})", value, amount); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f6ba9f0c2b633..dabf21c26b3d5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -461,13 +461,9 @@ bitflags! { // Currently we can't normalize projections w/ bound regions. const HAS_NORMALIZABLE_PROJECTION = 1 << 12; - // Set if this includes a "canonical" type or region var -- - // ought to be true only for the results of canonicalization. - const HAS_CANONICAL_VARS = 1 << 13; - /// Does this have any `ReLateBound` regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 14; + const HAS_RE_LATE_BOUND = 1 << 13; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_SELF.bits | @@ -488,7 +484,6 @@ bitflags! { TypeFlags::HAS_TY_CLOSURE.bits | TypeFlags::HAS_FREE_LOCAL_NAMES.bits | TypeFlags::KEEP_IN_LOCAL_TCX.bits | - TypeFlags::HAS_CANONICAL_VARS.bits | TypeFlags::HAS_RE_LATE_BOUND.bits; } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e57e7d759d517..7b00740a9811b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -77,6 +77,17 @@ impl BoundRegion { _ => false, } } + + /// When canonicalizing, we replace unbound inference variables and free + /// regions with anonymous late bound regions. This method asserts that + /// we have an anonymous late bound region, which hence may refer to + /// a canonical variable. + pub fn as_bound_var(&self) -> BoundVar { + match *self { + BoundRegion::BrAnon(var) => BoundVar::from_u32(var), + _ => bug!("bound region is not anonymous"), + } + } } /// N.B., If you change this, you'll probably want to change the corresponding @@ -758,11 +769,11 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } -/// Binder is a binder for higher-ranked lifetimes. It is part of the +/// Binder is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == /// Binder`). Note that when we instantiate, -/// erase, or otherwise "discharge" these bound regions, we change the +/// erase, or otherwise "discharge" these bound vars, we change the /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -770,7 +781,7 @@ pub struct Binder(T); impl Binder { /// Wraps `value` in a binder, asserting that `value` does not - /// contain any bound regions that would be bound by the + /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. pub fn dummy<'tcx>(value: T) -> Binder @@ -780,9 +791,8 @@ impl Binder { Binder(value) } - /// Wraps `value` in a binder, binding late-bound regions (if any). - pub fn bind<'tcx>(value: T) -> Binder - { + /// Wraps `value` in a binder, binding higher-ranked vars (if any). + pub fn bind<'tcx>(value: T) -> Binder { Binder(value) } @@ -1169,9 +1179,6 @@ pub enum RegionKind { /// `ClosureRegionRequirements` that are produced by MIR borrowck. /// See `ClosureRegionRequirements` for more details. ReClosureBound(RegionVid), - - /// Canonicalized region, used only when preparing a trait query. - ReCanonical(BoundVar), } impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {} @@ -1381,7 +1388,6 @@ impl RegionKind { RegionKind::ReEmpty => false, RegionKind::ReErased => false, RegionKind::ReClosureBound(..) => false, - RegionKind::ReCanonical(..) => false, } } @@ -1468,10 +1474,6 @@ impl RegionKind { } ty::ReErased => { } - ty::ReCanonical(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_CANONICAL_VARS; - } ty::ReClosureBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 6bdbeb8f604fc..498d704eb9e28 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -475,8 +475,8 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { } /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs - /// when we are substituting a type with escaping regions into a context where we have passed - /// through region binders. That's quite a mouthful. Let's see an example: + /// when we are substituting a type with escaping bound vars into a context where we have + /// passed through binders. That's quite a mouthful. Let's see an example: /// /// ``` /// type Func = fn(A); @@ -524,7 +524,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { return ty; } - let result = ty::fold::shift_vars(self.tcx(), self.binders_passed, &ty); + let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed); debug!("shift_vars: shifted result = {:?}", result); result @@ -534,7 +534,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { if self.binders_passed == 0 || !region.has_escaping_bound_vars() { return region; } - self.tcx().mk_region(ty::fold::shift_region(*region, self.binders_passed)) + ty::fold::shift_region(self.tcx, region, self.binders_passed) } } @@ -556,7 +556,8 @@ impl CanonicalUserSubsts<'tcx> { self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { UnpackedKind::Type(ty) => match ty.sty { - ty::Bound(ref b) => { + ty::Bound(b) => { + // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(b.index, ty::INNERMOST); cvar == b.var } @@ -564,7 +565,11 @@ impl CanonicalUserSubsts<'tcx> { }, UnpackedKind::Lifetime(r) => match r { - ty::ReCanonical(cvar1) => cvar == *cvar1, + ty::ReLateBound(index, br) => { + // We only allow a `ty::INNERMOST` index in substitutions. + assert_eq!(*index, ty::INNERMOST); + cvar == br.as_bound_var() + } _ => false, }, } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 4a5d956ed4e8e..92513621be498 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -798,9 +798,6 @@ define_print! { ty::ReEarlyBound(ref data) => { write!(f, "{}", data.name) } - ty::ReCanonical(_) => { - write!(f, "'_") - } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { @@ -868,10 +865,6 @@ define_print! { write!(f, "{:?}", vid) } - ty::ReCanonical(c) => { - write!(f, "'?{}", c.index()) - } - ty::RePlaceholder(placeholder) => { write!(f, "RePlaceholder({:?})", placeholder) } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index d9b64527700fc..abdeb430d260c 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -425,7 +425,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // These cannot exist in borrowck RegionKind::ReVar(..) | - RegionKind::ReCanonical(..) | RegionKind::RePlaceholder(..) | RegionKind::ReClosureBound(..) | RegionKind::ReErased => span_bug!(borrow_span, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 1f83c30a3876a..78a31ed668fca 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -363,7 +363,6 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { ty::ReStatic => self.item_ub, - ty::ReCanonical(_) | ty::ReEmpty | ty::ReClosureBound(..) | ty::ReLateBound(..) | diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 2b671891fca6d..99372a511a9de 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -277,8 +277,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { | ty::RePlaceholder(..) | ty::ReEmpty | ty::ReErased - | ty::ReClosureBound(..) - | ty::ReCanonical(..) => None, + | ty::ReClosureBound(..) => None, } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1978f86545e7b..229bcab9bd890 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1748,7 +1748,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { self.region_bounds.iter().map(|&(region_bound, span)| { // account for the binder being introduced below; no need to shift `param_ty` // because, at present at least, it can only refer to early-bound regions - let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1)); + let region_bound = ty::fold::shift_region(tcx, region_bound, 1); let outlives = ty::OutlivesPredicate(param_ty, region_bound); (ty::Binder::dummy(outlives).to_predicate(), span) }).chain( diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 96b75c4792d75..d748d93d8988e 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -167,7 +167,6 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool RegionKind::ReEmpty | RegionKind::ReErased | RegionKind::ReClosureBound(..) - | RegionKind::ReCanonical(..) | RegionKind::ReScope(..) | RegionKind::ReVar(..) | RegionKind::RePlaceholder(..) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index b11b034ee13cc..47d34c909961e 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -427,7 +427,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // way early-bound regions do, so we skip them here. } - ty::ReCanonical(_) | ty::ReFree(..) | ty::ReClosureBound(..) | ty::ReScope(..) | diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 70b90539ac410..984014e1916f8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1260,7 +1260,6 @@ impl Clean> for ty::RegionKind { ty::RePlaceholder(..) | ty::ReEmpty | ty::ReClosureBound(_) | - ty::ReCanonical(_) | ty::ReErased => None } } From b86d7000035914591d58efd8233546298f6deb95 Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 24 Oct 2018 22:30:34 +0200 Subject: [PATCH 11/33] Rename `Binder::no_late_bound_regions` to `Binder::no_bound_vars` --- src/librustc/infer/outlives/verify.rs | 2 +- src/librustc/traits/auto_trait.rs | 4 ++-- src/librustc/traits/fulfill.rs | 8 ++++---- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/project.rs | 2 +- src/librustc/traits/query/outlives_bounds.rs | 2 +- src/librustc/traits/select.rs | 4 ++-- src/librustc/ty/sty.rs | 14 +++++++------- src/librustc_codegen_llvm/base.rs | 2 +- .../nll/type_check/constraint_conversion.rs | 4 ++-- .../borrow_check/nll/type_check/mod.rs | 4 ++-- src/librustc_mir/monomorphize/collector.rs | 2 +- src/librustc_mir/shim.rs | 4 +++- src/librustc_mir/transform/lower_128bit.rs | 2 +- src/librustc_traits/implied_outlives_bounds.rs | 4 ++-- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/intrinsic.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- 18 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index e1db295b7e14d..88d45671b9afd 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -323,7 +323,7 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> { predicates .into_iter() .filter_map(|p| p.as_ref().to_opt_type_outlives()) - .filter_map(|p| p.no_late_bound_regions()) + .filter_map(|p| p.no_bound_vars()) .filter(move |p| compare_ty(p.0)) } } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 50ca6ca78ab3a..e87e425762d56 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -683,8 +683,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } &ty::Predicate::TypeOutlives(ref binder) => { match ( - binder.no_late_bound_regions(), - binder.map_bound_ref(|pred| pred.0).no_late_bound_regions(), + binder.no_bound_vars(), + binder.map_bound_ref(|pred| pred.0).no_bound_vars(), ) { (None, Some(t_a)) => { select.infcx().register_region_obligation_with_cause( diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 0ccdb19616a54..fe3cfc403d773 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -351,15 +351,15 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, } ty::Predicate::TypeOutlives(ref binder) => { - // Check if there are higher-ranked regions. - match binder.no_late_bound_regions() { + // Check if there are higher-ranked vars. + match binder.no_bound_vars() { // If there are, inspect the underlying type further. None => { // Convert from `Binder>` to `Binder`. let binder = binder.map_bound_ref(|pred| pred.0); - // Check if the type has any bound regions. - match binder.no_late_bound_regions() { + // Check if the type has any bound vars. + match binder.no_bound_vars() { // If so, this obligation is an error (for now). Eventually we should be // able to support additional cases here, like `for<'a> &'a str: 'a`. // NOTE: this is duplicate-implemented between here and fulfillment. diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8bceebb23950c..2a1e5fa8e19ea 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -352,7 +352,7 @@ impl<'tcx> GoalKind<'tcx> { domain_goal: PolyDomainGoal<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, ) -> GoalKind<'tcx> { - match domain_goal.no_late_bound_regions() { + match domain_goal.no_bound_vars() { Some(p) => p.into_goal(), None => GoalKind::Quantified( QuantifierKind::Universal, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b62724a8aa263..09516dc50f30b 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1619,7 +1619,7 @@ impl<'cx, 'gcx, 'tcx> ProjectionCacheKey<'tcx> { let infcx = selcx.infcx(); // We don't do cross-snapshot caching of obligations with escaping regions, // so there's no cache key to use - predicate.no_late_bound_regions() + predicate.no_bound_vars() .map(|predicate| ProjectionCacheKey { // We don't attempt to match up with a specific type-variable state // from a specific call to `opt_normalize_projection_type` - if diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index 99f557d44d9aa..b3fae3bab3471 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -164,7 +164,7 @@ pub fn explicit_outlives_bounds<'tcx>( ty::Predicate::ClosureKind(..) | ty::Predicate::TypeOutlives(..) | ty::Predicate::ConstEvaluatable(..) => None, - ty::Predicate::RegionOutlives(ref data) => data.no_late_bound_regions().map( + ty::Predicate::RegionOutlives(ref data) => data.no_bound_vars().map( |ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a), ), }) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index bb1649be1320b..44f32aadab133 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2144,7 +2144,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T: Trait // so it seems ok if we (conservatively) fail to accept that `Unsize` // obligation above. Should be possible to extend this in the future. - let source = match obligation.self_ty().no_late_bound_regions() { + let source = match obligation.self_ty().no_bound_vars() { Some(t) => t, None => { // Don't add any candidates if there are bound regions. @@ -3213,7 +3213,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // assemble_candidates_for_unsizing should ensure there are no late bound // regions here. See the comment there for more details. let source = self.infcx - .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap()); + .shallow_resolve(obligation.self_ty().no_bound_vars().unwrap()); let target = obligation .predicate .skip_binder() diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7b00740a9811b..3d3cf88ad35f0 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -799,10 +799,10 @@ impl Binder { /// Skips the binder and returns the "bound" value. This is a /// risky thing to do because it's easy to get confused about /// debruijn indices and the like. It is usually better to - /// discharge the binder using `no_late_bound_regions` or + /// discharge the binder using `no_bound_vars` or /// `replace_late_bound_regions` or something like /// that. `skip_binder` is only valid when you are either - /// extracting data that has nothing to do with bound regions, you + /// extracting data that has nothing to do with bound vars, you /// are doing some sort of test that does not involve bound /// regions, or you are being very careful about your depth /// accounting. @@ -811,7 +811,7 @@ impl Binder { /// /// - extracting the def-id from a PolyTraitRef; /// - comparing the self type of a PolyTraitRef to see if it is equal to - /// a type parameter `X`, since the type `X` does not reference any regions + /// a type parameter `X`, since the type `X` does not reference any regions pub fn skip_binder(&self) -> &T { &self.0 } @@ -833,17 +833,17 @@ impl Binder { } /// Unwraps and returns the value within, but only if it contains - /// no bound regions at all. (In other words, if this binder -- + /// no bound vars at all. (In other words, if this binder -- /// and indeed any enclosing binder -- doesn't bind anything at /// all.) Otherwise, returns `None`. /// /// (One could imagine having a method that just unwraps a single - /// binder, but permits late-bound regions bound by enclosing + /// binder, but permits late-bound vars bound by enclosing /// binders, but that would require adjusting the debruijn /// indices, and given the shallow binding structure we often use, /// would not be that useful.) - pub fn no_late_bound_regions<'tcx>(self) -> Option - where T : TypeFoldable<'tcx> + pub fn no_bound_vars<'tcx>(self) -> Option + where T: TypeFoldable<'tcx> { if self.skip_binder().has_escaping_bound_vars() { None diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 614a562846e86..4a7ac0379ee5a 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -558,7 +558,7 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { // regions must appear in the argument // listing. let main_ret_ty = cx.tcx.erase_regions( - &main_ret_ty.no_late_bound_regions().unwrap(), + &main_ret_ty.no_bound_vars().unwrap(), ); if declare::get_defined_value(cx, "main").is_some() { diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs index 994f20a011d65..44566206820cd 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs @@ -82,9 +82,9 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { // when we move to universes, we will, and this assertion // will start to fail. let ty::OutlivesPredicate(k1, r2) = - query_constraint.no_late_bound_regions().unwrap_or_else(|| { + query_constraint.no_bound_vars().unwrap_or_else(|| { bug!( - "query_constraint {:?} contained bound regions", + "query_constraint {:?} contained bound vars", query_constraint, ); }); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index c0f8e936f09e2..85272898351de 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -2252,8 +2252,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { .enumerate() .filter_map(|(idx, constraint)| { let ty::OutlivesPredicate(k1, r2) = - constraint.no_late_bound_regions().unwrap_or_else(|| { - bug!("query_constraint {:?} contained bound regions", constraint,); + constraint.no_bound_vars().unwrap_or_else(|| { + bug!("query_constraint {:?} contained bound vars", constraint,); }); match k1.unpack() { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 27a2a0481736c..9ea894642f081 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1066,7 +1066,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { // regions must appear in the argument // listing. let main_ret_ty = self.tcx.erase_regions( - &main_ret_ty.no_late_bound_regions().unwrap(), + &main_ret_ty.no_bound_vars().unwrap(), ); let start_instance = Instance::resolve( diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 4b26094b9fc28..bb7b469b5a973 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -826,7 +826,9 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let param_env = gcx.param_env(def_id); // Normalize the sig. - let sig = gcx.fn_sig(def_id).no_late_bound_regions().expect("LBR in ADT constructor signature"); + let sig = gcx.fn_sig(def_id) + .no_bound_vars() + .expect("LBR in ADT constructor signature"); let sig = gcx.normalize_erasing_regions(param_env, sig); let (adt_def, substs) = match sig.output().sty { diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index bd7d9d367618b..80072153167f3 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -143,7 +143,7 @@ fn check_lang_item_type<'a, 'tcx, D>( { let did = tcx.require_lang_item(lang_item); let poly_sig = tcx.fn_sig(did); - let sig = poly_sig.no_late_bound_regions().unwrap(); + let sig = poly_sig.no_bound_vars().unwrap(); let lhs_ty = lhs.ty(local_decls, tcx); let rhs_ty = rhs.ty(local_decls, tcx); let place_ty = place.ty(local_decls, tcx).to_ty(tcx); diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 228125b11b66a..3c2ef1ae6d19f 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -122,14 +122,14 @@ fn compute_implied_outlives_bounds<'tcx>( vec![] } - ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() { + ty::Predicate::RegionOutlives(ref data) => match data.no_bound_vars() { None => vec![], Some(ty::OutlivesPredicate(r_a, r_b)) => { vec![OutlivesBound::RegionSubRegion(r_b, r_a)] } }, - ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() { + ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() { None => vec![], Some(ty::OutlivesPredicate(ty_a, r_b)) => { let ty_a = infcx.resolve_type_vars_if_possible(&ty_a); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3204ef556f5dd..40f2072079a5a 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -816,7 +816,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } // Replace constructor type with constructed type for tuple struct patterns. let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); + let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index da96d4f0cba42..3156458b4aa4a 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -419,7 +419,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap::default(); let sig = tcx.fn_sig(def_id); - let sig = sig.no_late_bound_regions().unwrap(); + let sig = sig.no_bound_vars().unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, "platform-specific intrinsic has invalid number of \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index eb52a013b0566..bf3887ee8fcdd 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { item_def_id: DefId, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx> { - if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() { + if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { // no late-bound regions, we can just ignore the binder From 235c8488220eb1602d1319c29150588333a47ed5 Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 24 Oct 2018 23:41:40 +0200 Subject: [PATCH 12/33] Extend `ty::fold::RegionReplacer` to `ty::fold::BoundVarReplacer` Use the new `BoundVarReplacer` to perform canonical substitutions. --- src/librustc/infer/canonical/substitute.rs | 89 ++------- src/librustc/ty/fold.rs | 200 ++++++++++++++------- 2 files changed, 149 insertions(+), 140 deletions(-) diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 7839c8922660a..3fd86f9c6a1d9 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -17,9 +17,9 @@ //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html use infer::canonical::{Canonical, CanonicalVarValues}; -use ty::fold::{TypeFoldable, TypeFolder}; +use ty::fold::TypeFoldable; use ty::subst::UnpackedKind; -use ty::{self, Ty, TyCtxt}; +use ty::{self, TyCtxt}; impl<'tcx, V> Canonical<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value @@ -65,82 +65,21 @@ where { if var_values.var_values.is_empty() { value.clone() - } else if !value.has_escaping_bound_vars() { - // There are no bound vars to substitute. - value.clone() } else { - value.fold_with(&mut CanonicalVarValuesSubst { - tcx, - var_values, - binder_index: ty::INNERMOST, - }) - } -} - -struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> { - tcx: TyCtxt<'cx, 'gcx, 'tcx>, - var_values: &'cx CanonicalVarValues<'tcx>, - binder_index: ty::DebruijnIndex, -} - -impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> { - fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> { - self.tcx - } - - fn fold_binder(&mut self, t: &ty::Binder) -> ty::Binder - where T: TypeFoldable<'tcx> - { - self.binder_index.shift_in(1); - let t = t.super_fold_with(self); - self.binder_index.shift_out(1); - t - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { - ty::Bound(b) => { - if b.index == self.binder_index { - match self.var_values.var_values[b.var].unpack() { - UnpackedKind::Type(ty) => ty::fold::shift_vars( - self.tcx, - &ty, - self.binder_index.index() as u32 - ), - r => bug!("{:?} is a type but value is {:?}", b, r), - } - } else { - t - } + let fld_r = |br: ty::BoundRegion| { + match var_values.var_values[br.as_bound_var()].unpack() { + UnpackedKind::Lifetime(l) => l, + r => bug!("{:?} is a region but value is {:?}", br, r), } - _ => { - if !t.has_vars_bound_at_or_above(self.binder_index) { - // Nothing more to substitute. - t - } else { - t.super_fold_with(self) - } - } - } - } + }; - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match r { - ty::RegionKind::ReLateBound(index, br) => { - if *index == self.binder_index { - match self.var_values.var_values[br.as_bound_var()].unpack() { - UnpackedKind::Lifetime(l) => ty::fold::shift_region( - self.tcx, - l, - self.binder_index.index() as u32, - ), - r => bug!("{:?} is a region but value is {:?}", br, r), - } - } else { - r - } + let fld_t = |bound_ty: ty::BoundTy| { + match var_values.var_values[bound_ty.var].unpack() { + UnpackedKind::Type(ty) => ty, + r => bug!("{:?} is a type but value is {:?}", bound_ty, r), } - _ => r.super_fold_with(self), - } + }; + + tcx.replace_escaping_bound_vars(value, fld_r, fld_t) } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 31542582f9499..06cc316f7883a 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -416,11 +416,10 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> { } /////////////////////////////////////////////////////////////////////////// -// Late-bound region replacer +// Bound vars replacer -// Replaces the escaping regions in a type. - -struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +/// Replaces the escaping bound vars (late bound regions or bound types) in a type. +struct BoundVarReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, /// As with `RegionFolder`, represents the index of a binder *just outside* @@ -428,7 +427,82 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { current_index: ty::DebruijnIndex, fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), - map: BTreeMap> + fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> ty::Ty<'tcx> + 'a), +} + +impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> { + fn new( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + fld_r: &'a mut F, + fld_t: &'a mut G + ) -> Self + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + G: FnMut(ty::BoundTy) -> ty::Ty<'tcx> + { + BoundVarReplacer { + tcx, + current_index: ty::INNERMOST, + fld_r, + fld_t, + } + } +} + +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } + + fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.sty { + ty::Bound(bound_ty) => { + if bound_ty.index == self.current_index { + let fld_t = &mut self.fld_t; + let ty = fld_t(bound_ty); + ty::fold::shift_vars( + self.tcx, + &ty, + self.current_index.as_u32() + ) + } else { + t + } + } + _ => { + if !t.has_vars_bound_at_or_above(self.current_index) { + // Nothing more to substitute. + t + } else { + t.super_fold_with(self) + } + } + } + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match *r { + ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { + let fld_r = &mut self.fld_r; + let region = fld_r(br); + if let ty::ReLateBound(debruijn1, br) = *region { + // If the callback returns a late-bound region, + // that region should always use the INNERMOST + // debruijn index. Then we adjust it to the + // correct depth. + assert_eq!(debruijn1, ty::INNERMOST); + self.tcx.mk_region(ty::ReLateBound(debruijn, br)) + } else { + region + } + } + _ => r + } + } } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// same `BoundRegion` will reuse the previous result. A map is /// returned at the end with each bound region and the free region /// that replaced it. - pub fn replace_late_bound_regions(self, + /// + /// This method only replaces late bound regions and the result may still + /// contain escaping bound types. + pub fn replace_late_bound_regions( + self, value: &Binder, - mut f: F) - -> (T, BTreeMap>) - where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>, - T : TypeFoldable<'tcx>, + mut fld_r: F + ) -> (T, BTreeMap>) + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + T: TypeFoldable<'tcx> { - let mut replacer = RegionReplacer::new(self, &mut f); + let mut map = BTreeMap::new(); + let mut real_fldr = |br| { + *map.entry(br).or_insert_with(|| fld_r(br)) + }; + + // identity for bound types + let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty)); + + let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t); let result = value.skip_binder().fold_with(&mut replacer); - (result, replacer.map) + (result, map) + } + + /// Replace all escaping bound vars. The `fld_r` closure replaces escaping + /// bound regions while the `flr_t` closure replaces escaping bound types. + pub fn replace_escaping_bound_vars( + self, + value: &T, + mut fld_r: F, + mut fld_t: G + ) -> T + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>, + T: TypeFoldable<'tcx> + { + if !value.has_escaping_bound_vars() { + value.clone() + } else { + let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t); + let result = value.fold_with(&mut replacer); + result + } + } + + /// Replace all types or regions bound by the given `Binder`. The `fld_r` + /// closure replaces bound regions while the `flr_t` closure replaces bound + /// types. + pub fn replace_bound_vars( + self, + value: &Binder, + fld_r: F, + fld_t: G + ) -> T + where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>, + T: TypeFoldable<'tcx> + { + self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t) } /// Replace any late-bound regions bound in `value` with @@ -549,59 +672,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> { - fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fld_r: &'a mut F) - -> RegionReplacer<'a, 'gcx, 'tcx> - where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx> - { - RegionReplacer { - tcx, - current_index: ty::INNERMOST, - fld_r, - map: BTreeMap::default() - } - } -} - -impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } - - fn fold_binder>(&mut self, t: &ty::Binder) -> ty::Binder { - self.current_index.shift_in(1); - let t = t.super_fold_with(self); - self.current_index.shift_out(1); - t - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_vars_bound_at_or_above(self.current_index) { - return t; - } - - t.super_fold_with(self) - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { - let fld_r = &mut self.fld_r; - let region = *self.map.entry(br).or_insert_with(|| fld_r(br)); - if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, - // that region should always use the INNERMOST - // debruijn index. Then we adjust it to the - // correct depth. - assert_eq!(debruijn1, ty::INNERMOST); - self.tcx.mk_region(ty::ReLateBound(debruijn, br)) - } else { - region - } - } - _ => r - } - } -} - /////////////////////////////////////////////////////////////////////////// // Shifter // From 47499ccb49e593727569af4d99900e4b74204ac4 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 25 Oct 2018 14:13:24 +0200 Subject: [PATCH 13/33] Fix doc comment --- src/librustc/infer/canonical/canonicalizer.rs | 2 +- src/librustc/ty/fold.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 323057415afdd..e969e10f1b3c8 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -467,7 +467,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { let var = self.canonical_var(info, r.into()); let region = ty::ReLateBound( self.binder_index, - ty::BoundRegion::BrAnon(var.index() as u32) + ty::BoundRegion::BrAnon(var.as_u32()) ); self.tcx().mk_region(region) } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 06cc316f7883a..8c822adf7b023 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -539,7 +539,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Replace all escaping bound vars. The `fld_r` closure replaces escaping - /// bound regions while the `flr_t` closure replaces escaping bound types. + /// bound regions while the `fld_t` closure replaces escaping bound types. pub fn replace_escaping_bound_vars( self, value: &T, @@ -560,7 +560,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Replace all types or regions bound by the given `Binder`. The `fld_r` - /// closure replaces bound regions while the `flr_t` closure replaces bound + /// closure replaces bound regions while the `fld_t` closure replaces bound /// types. pub fn replace_bound_vars( self, From 18eeed5b148897176a5adb1ba237ce8b0f630b9b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Oct 2018 14:45:08 +0200 Subject: [PATCH 14/33] Move cg_llvm::back::linker to cg_utils --- src/librustc_codegen_llvm/back/archive.rs | 24 +--------- src/librustc_codegen_llvm/back/link.rs | 7 +-- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 6 +-- src/librustc_codegen_llvm/lib.rs | 30 ++---------- src/librustc_codegen_utils/Cargo.toml | 2 + .../command.rs | 0 src/librustc_codegen_utils/lib.rs | 47 +++++++++++++++++++ .../back => librustc_codegen_utils}/linker.rs | 27 ++++++----- .../symbol_export.rs | 2 +- 10 files changed, 80 insertions(+), 67 deletions(-) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/command.rs (100%) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/linker.rs (98%) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/symbol_export.rs (99%) diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index af9efc6d7c417..ce4cb1ea3a042 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -52,28 +52,6 @@ enum Addition { }, } -pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) - -> PathBuf { - // On Windows, static libraries sometimes show up as libfoo.a and other - // times show up as foo.lib - let oslibname = format!("{}{}{}", - sess.target.target.options.staticlib_prefix, - name, - sess.target.target.options.staticlib_suffix); - let unixlibname = format!("lib{}.a", name); - - for path in search_paths { - debug!("looking for {} inside {:?}", name, path); - let test = path.join(&oslibname); - if test.exists() { return test } - if oslibname != unixlibname { - let test = path.join(&unixlibname); - if test.exists() { return test } - } - } - sess.fatal(&format!("could not find native static library `{}`, \ - perhaps an -L flag is missing?", name)); -} fn is_relevant_child(c: &Child) -> bool { match c.name() { @@ -128,7 +106,7 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. pub fn add_native_library(&mut self, name: &str) { - let location = find_library(name, &self.config.lib_search_paths, + let location = ::rustc_codegen_utils::find_library(name, &self.config.lib_search_paths, self.config.sess); self.add_archive(&location, |_| false).unwrap_or_else(|e| { self.config.sess.fatal(&format!("failed to add native library {}: {}", diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 86c6a5e65b0e9..dd95c3d986299 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -12,8 +12,6 @@ use back::wasm; use cc::windows_registry; use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::bytecode::RLIB_BYTECODE_EXTENSION; -use super::linker::Linker; -use super::command::Command; use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; @@ -31,6 +29,8 @@ use rustc::hir::def_id::CrateNum; use tempfile::{Builder as TempFileBuilder, TempDir}; use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor}; use rustc_data_structures::fx::FxHashSet; +use rustc_codegen_utils::linker::Linker; +use rustc_codegen_utils::command::Command; use context::get_reloc_model; use llvm; @@ -701,7 +701,8 @@ fn link_natively(sess: &Session, } { - let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor); + let target_cpu = ::llvm_util::target_cpu(sess); + let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu); link_args(&mut *linker, flavor, sess, crate_type, tmpdir, out_filename, codegen_results); cmd = linker.finalize(); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 61856236a1491..8f940e0d22a83 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -9,7 +9,6 @@ // except according to those terms. use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION}; -use back::symbol_export; use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename}; use errors::{FatalError, Handler}; @@ -24,6 +23,7 @@ use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config::{self, Lto}; use rustc::util::common::time_ext; use rustc_data_structures::fx::FxHashMap; +use rustc_codegen_utils::symbol_export; use time_graph::Timeline; use {ModuleCodegen, ModuleLlvm, ModuleKind}; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 81619c219757b..333a778e7765f 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -12,9 +12,6 @@ use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule}; use back::link::{self, get_linker, remove}; -use back::command::Command; -use back::linker::LinkerInfo; -use back::symbol_export::ExportedSymbols; use base; use consts; use memmap; @@ -38,6 +35,9 @@ use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passe use rustc_fs_util::{path2cstr, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::svh::Svh; +use rustc_codegen_utils::command::Command; +use rustc_codegen_utils::linker::LinkerInfo; +use rustc_codegen_utils::symbol_export::ExportedSymbols; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use errors::emitter::{Emitter}; use syntax::attr; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 63a8ab077e5ae..f64cf0c7364dd 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -71,7 +71,6 @@ use back::bytecode::RLIB_BYTECODE_EXTENSION; pub use llvm_util::target_features; use std::any::Any; -use std::path::{PathBuf}; use std::sync::mpsc; use rustc_data_structures::sync::Lrc; @@ -87,20 +86,17 @@ use rustc::util::time_graph; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::util::profiling::ProfileCategory; use rustc_mir::monomorphize; +use rustc_codegen_utils::{CompiledModule, ModuleKind}; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::svh::Svh; mod diagnostics; mod back { - pub use rustc_codegen_utils::symbol_names; mod archive; pub mod bytecode; - mod command; - pub mod linker; pub mod link; pub mod lto; - pub mod symbol_export; pub mod write; mod rpath; pub mod wasm; @@ -194,14 +190,14 @@ impl CodegenBackend for LlvmCodegenBackend { } fn provide(&self, providers: &mut ty::query::Providers) { - back::symbol_names::provide(providers); - back::symbol_export::provide(providers); + rustc_codegen_utils::symbol_export::provide(providers); + rustc_codegen_utils::symbol_names::provide(providers); base::provide(providers); attributes::provide(providers); } fn provide_extern(&self, providers: &mut ty::query::Providers) { - back::symbol_export::provide_extern(providers); + rustc_codegen_utils::symbol_export::provide_extern(providers); base::provide_extern(providers); attributes::provide_extern(providers); } @@ -281,13 +277,6 @@ struct CachedModuleCodegen { source: WorkProduct, } -#[derive(Copy, Clone, Debug, PartialEq)] -enum ModuleKind { - Regular, - Metadata, - Allocator, -} - impl ModuleCodegen { fn into_compiled_module(self, emit_obj: bool, @@ -321,15 +310,6 @@ impl ModuleCodegen { } } -#[derive(Debug)] -struct CompiledModule { - name: String, - kind: ModuleKind, - object: Option, - bytecode: Option, - bytecode_compressed: Option, -} - struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, @@ -377,7 +357,7 @@ struct CodegenResults { crate_hash: Svh, metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, - linker_info: back::linker::LinkerInfo, + linker_info: rustc_codegen_utils::linker::LinkerInfo, crate_info: CrateInfo, } diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index a1f4a323f849e..3a09e8e4b5606 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -13,9 +13,11 @@ test = false flate2 = "1.0" log = "0.4" +serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_mir = { path = "../librustc_mir" } diff --git a/src/librustc_codegen_llvm/back/command.rs b/src/librustc_codegen_utils/command.rs similarity index 100% rename from src/librustc_codegen_llvm/back/command.rs rename to src/librustc_codegen_utils/command.rs diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 03b3b20a4e772..89cf19d047216 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -30,8 +30,10 @@ extern crate flate2; #[macro_use] extern crate log; +extern crate serialize; #[macro_use] extern crate rustc; +extern crate rustc_allocator; extern crate rustc_target; extern crate rustc_mir; extern crate rustc_incremental; @@ -40,10 +42,16 @@ extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; extern crate rustc_metadata_utils; +use std::path::PathBuf; + +use rustc::session::Session; use rustc::ty::TyCtxt; +pub mod command; pub mod link; +pub mod linker; pub mod codegen_backend; +pub mod symbol_export; pub mod symbol_names; pub mod symbol_names_test; @@ -61,4 +69,43 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) { } } +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ModuleKind { + Regular, + Metadata, + Allocator, +} + +#[derive(Debug)] +pub struct CompiledModule { + pub name: String, + pub kind: ModuleKind, + pub object: Option, + pub bytecode: Option, + pub bytecode_compressed: Option, +} + +pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) + -> PathBuf { + // On Windows, static libraries sometimes show up as libfoo.a and other + // times show up as foo.lib + let oslibname = format!("{}{}{}", + sess.target.target.options.staticlib_prefix, + name, + sess.target.target.options.staticlib_suffix); + let unixlibname = format!("lib{}.a", name); + + for path in search_paths { + debug!("looking for {} inside {:?}", name, path); + let test = path.join(&oslibname); + if test.exists() { return test } + if oslibname != unixlibname { + let test = path.join(&unixlibname); + if test.exists() { return test } + } + } + sess.fatal(&format!("could not find native static library `{}`, \ + perhaps an -L flag is missing?", name)); +} + __build_diagnostic_array! { librustc_codegen_utils, DIAGNOSTICS } diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_utils/linker.rs similarity index 98% rename from src/librustc_codegen_llvm/back/linker.rs rename to src/librustc_codegen_utils/linker.rs index e18c8b9dec463..c1f41fd509a14 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_utils/linker.rs @@ -15,9 +15,7 @@ use std::io::prelude::*; use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; -use back::archive; -use back::command::Command; -use back::symbol_export; +use command::Command; use rustc::hir::def_id::{LOCAL_CRATE, CrateNum}; use rustc::middle::dependency_format::Linkage; use rustc::session::Session; @@ -26,7 +24,6 @@ use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use serialize::{json, Encoder}; -use llvm_util; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. @@ -43,10 +40,13 @@ impl LinkerInfo { } } - pub fn to_linker<'a>(&'a self, - cmd: Command, - sess: &'a Session, - flavor: LinkerFlavor) -> Box { + pub fn to_linker<'a>( + &'a self, + cmd: Command, + sess: &'a Session, + flavor: LinkerFlavor, + target_cpu: &'a str, + ) -> Box { match flavor { LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { @@ -70,6 +70,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: false, + target_cpu, }) as Box } @@ -82,6 +83,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: true, + target_cpu, }) as Box } @@ -144,6 +146,7 @@ pub struct GccLinker<'a> { hinted_static: bool, // Keeps track of the current hinting mode. // Link as ld is_ld: bool, + target_cpu: &'a str, } impl<'a> GccLinker<'a> { @@ -204,7 +207,8 @@ impl<'a> GccLinker<'a> { }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); - self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); + let target_cpu = self.target_cpu; + self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu)); match self.sess.lto() { config::Lto::Thin | @@ -263,7 +267,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = archive::find_library(lib, search_path, &self.sess); + let lib = ::find_library(lib, search_path, &self.sess); self.linker_arg(&lib); } } @@ -898,7 +902,8 @@ impl<'a> Linker for EmLinker<'a> { fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { let mut symbols = Vec::new(); - let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); + let export_threshold = + ::symbol_export::crates_export_threshold(&[crate_type]); for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { if level.is_below_threshold(export_threshold) { symbols.push(symbol.symbol_name(tcx).to_string()); diff --git a/src/librustc_codegen_llvm/back/symbol_export.rs b/src/librustc_codegen_utils/symbol_export.rs similarity index 99% rename from src/librustc_codegen_llvm/back/symbol_export.rs rename to src/librustc_codegen_utils/symbol_export.rs index 6b1b0b94fd9d7..2d650f7f18d6f 100644 --- a/src/librustc_codegen_llvm/back/symbol_export.rs +++ b/src/librustc_codegen_utils/symbol_export.rs @@ -11,7 +11,7 @@ use rustc_data_structures::sync::Lrc; use std::sync::Arc; -use monomorphize::Instance; +use rustc::ty::Instance; use rustc::hir; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; From 2bf01aacf5b238bfa13783ea2ee3c98bce2867d0 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 25 Oct 2018 15:40:06 +0200 Subject: [PATCH 15/33] Rename `as_bound_var` to `assert_bound_var` --- src/librustc/infer/canonical/query_response.rs | 2 +- src/librustc/infer/canonical/substitute.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index c365e8614eddb..e5e005401ace8 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -433,7 +433,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(index, ty::INNERMOST); - opt_values[br.as_bound_var()] = Some(*original_value); + opt_values[br.assert_bound_var()] = Some(*original_value); } } } diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs index 3fd86f9c6a1d9..b8c1ed236c0ba 100644 --- a/src/librustc/infer/canonical/substitute.rs +++ b/src/librustc/infer/canonical/substitute.rs @@ -67,7 +67,7 @@ where value.clone() } else { let fld_r = |br: ty::BoundRegion| { - match var_values.var_values[br.as_bound_var()].unpack() { + match var_values.var_values[br.assert_bound_var()].unpack() { UnpackedKind::Lifetime(l) => l, r => bug!("{:?} is a region but value is {:?}", br, r), } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3d3cf88ad35f0..6ac5cac5c4b8b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -82,7 +82,7 @@ impl BoundRegion { /// regions with anonymous late bound regions. This method asserts that /// we have an anonymous late bound region, which hence may refer to /// a canonical variable. - pub fn as_bound_var(&self) -> BoundVar { + pub fn assert_bound_var(&self) -> BoundVar { match *self { BoundRegion::BrAnon(var) => BoundVar::from_u32(var), _ => bug!("bound region is not anonymous"), diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 498d704eb9e28..c1aed36c92ddf 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -568,7 +568,7 @@ impl CanonicalUserSubsts<'tcx> { ty::ReLateBound(index, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(*index, ty::INNERMOST); - cvar == br.as_bound_var() + cvar == br.assert_bound_var() } _ => false, }, From 2b205dc49332c6c859dfdddb9f0a4a8bc7138859 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 25 Oct 2018 16:01:10 +0200 Subject: [PATCH 16/33] Substitute binders directly --- .../infer/canonical/query_response.rs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index e5e005401ace8..bf86fc99afee3 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -308,12 +308,14 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { // ...also include the other query region constraints from the query. output_query_region_constraints.extend( query_response.value.region_constraints.iter().filter_map(|r_c| { - let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below - let k1 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*k1)); - let r2 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*r2)); - if k1 != r2.map_bound(|bound| bound.into()) { - let predicate = ty::OutlivesPredicate(*k1.skip_binder(), *r2.skip_binder()); - Some(ty::Binder::bind(predicate)) + let r_c = substitute_value(self.tcx, &result_subst, r_c); + + // Screen out `'a: 'a` cases -- we skip the binder here but + // only care the inner values to one another, so they are still at + // consistent binding levels. + let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); + if k1 != r2.into() { + Some(r_c) } else { None } @@ -504,22 +506,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { unsubstituted_region_constraints .iter() .map(move |constraint| { - let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below - let k1 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*k1)); - let r2 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*r2)); + let constraint = substitute_value(self.tcx, result_subst, constraint); + let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below Obligation::new( cause.clone(), param_env, - match k1.skip_binder().unpack() { + match k1.unpack() { UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( ty::Binder::bind( - ty::OutlivesPredicate(r1, r2.skip_binder()) + ty::OutlivesPredicate(r1, r2) ) ), UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( ty::Binder::bind( - ty::OutlivesPredicate(t1, r2.skip_binder()) + ty::OutlivesPredicate(t1, r2) ) ), } From 029cf2f858f2b0260f615cfa53692bf1507c6676 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 25 Oct 2018 14:49:51 +0200 Subject: [PATCH 17/33] Move collect_and_partition_mono_items to rustc_mir --- src/Cargo.lock | 2 + src/librustc_codegen_llvm/base.rs | 155 +---------------- src/librustc_codegen_llvm/lib.rs | 4 +- src/librustc_mir/lib.rs | 1 + src/librustc_mir/monomorphize/partitioning.rs | 163 +++++++++++++++++- 5 files changed, 165 insertions(+), 160 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3361e81ecfe6d..2b57883151f4e 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2135,11 +2135,13 @@ dependencies = [ "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_allocator 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", "rustc_metadata_utils 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", + "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 614a562846e86..5ce74971a883e 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -54,7 +54,6 @@ use attributes; use builder::{Builder, MemFlags}; use callee; use common::{C_bool, C_bytes_in_context, C_i32, C_usize}; -use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; use rustc_mir::monomorphize::item::DefPathBasedNames; use common::{self, C_struct_in_context, C_array, val_ty}; use consts; @@ -64,20 +63,19 @@ use declare; use meth; use mir; use monomorphize::Instance; -use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt}; +use monomorphize::partitioning::{CodegenUnit, CodegenUnitExt}; use rustc_codegen_utils::symbol_names_test; use time_graph; -use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt}; +use mono_item::{MonoItem, MonoItemExt}; use type_::Type; use type_of::LayoutLlvmExt; -use rustc::util::nodemap::{FxHashMap, DefIdSet}; +use rustc::util::nodemap::FxHashMap; use CrateInfo; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::sync::Lrc; use std::any::Any; use std::ffi::CString; -use std::sync::Arc; use std::time::{Instant, Duration}; use std::i32; use std::cmp; @@ -963,128 +961,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { || rustc_incremental::save_dep_graph(tcx)); } -fn collect_and_partition_mono_items<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cnum: CrateNum, -) -> (Arc, Arc>>>) -{ - assert_eq!(cnum, LOCAL_CRATE); - - let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items { - Some(ref s) => { - let mode_string = s.to_lowercase(); - let mode_string = mode_string.trim(); - if mode_string == "eager" { - MonoItemCollectionMode::Eager - } else { - if mode_string != "lazy" { - let message = format!("Unknown codegen-item collection mode '{}'. \ - Falling back to 'lazy' mode.", - mode_string); - tcx.sess.warn(&message); - } - - MonoItemCollectionMode::Lazy - } - } - None => { - if tcx.sess.opts.cg.link_dead_code { - MonoItemCollectionMode::Eager - } else { - MonoItemCollectionMode::Lazy - } - } - }; - - let (items, inlining_map) = - time(tcx.sess, "monomorphization collection", || { - collector::collect_crate_mono_items(tcx, collection_mode) - }); - - tcx.sess.abort_if_errors(); - - ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter()); - - let strategy = if tcx.sess.opts.incremental.is_some() { - PartitioningStrategy::PerModule - } else { - PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) - }; - - let codegen_units = time(tcx.sess, "codegen unit partitioning", || { - partitioning::partition(tcx, - items.iter().cloned(), - strategy, - &inlining_map) - .into_iter() - .map(Arc::new) - .collect::>() - }); - - let mono_items: DefIdSet = items.iter().filter_map(|mono_item| { - match *mono_item { - MonoItem::Fn(ref instance) => Some(instance.def_id()), - MonoItem::Static(def_id) => Some(def_id), - _ => None, - } - }).collect(); - - if tcx.sess.opts.debugging_opts.print_mono_items.is_some() { - let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default(); - - for cgu in &codegen_units { - for (&mono_item, &linkage) in cgu.items() { - item_to_cgus.entry(mono_item) - .or_default() - .push((cgu.name().clone(), linkage)); - } - } - - let mut item_keys: Vec<_> = items - .iter() - .map(|i| { - let mut output = i.to_string(tcx); - output.push_str(" @@"); - let mut empty = Vec::new(); - let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); - cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone()); - cgus.dedup(); - for &(ref cgu_name, (linkage, _)) in cgus.iter() { - output.push_str(" "); - output.push_str(&cgu_name.as_str()); - - let linkage_abbrev = match linkage { - Linkage::External => "External", - Linkage::AvailableExternally => "Available", - Linkage::LinkOnceAny => "OnceAny", - Linkage::LinkOnceODR => "OnceODR", - Linkage::WeakAny => "WeakAny", - Linkage::WeakODR => "WeakODR", - Linkage::Appending => "Appending", - Linkage::Internal => "Internal", - Linkage::Private => "Private", - Linkage::ExternalWeak => "ExternalWeak", - Linkage::Common => "Common", - }; - - output.push_str("["); - output.push_str(linkage_abbrev); - output.push_str("]"); - } - output - }) - .collect(); - - item_keys.sort(); - - for item in item_keys { - println!("MONO_ITEM {}", item); - } - } - - (Arc::new(mono_items), Arc::new(codegen_units)) -} - impl CrateInfo { pub fn new(tcx: TyCtxt) -> CrateInfo { let mut info = CrateInfo { @@ -1174,12 +1050,6 @@ impl CrateInfo { } } -fn is_codegened_item(tcx: TyCtxt, id: DefId) -> bool { - let (all_mono_items, _) = - tcx.collect_and_partition_mono_items(LOCAL_CRATE); - all_mono_items.contains(&id) -} - fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString) -> Stats { @@ -1270,24 +1140,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -pub fn provide(providers: &mut Providers) { - providers.collect_and_partition_mono_items = - collect_and_partition_mono_items; - - providers.is_codegened_item = is_codegened_item; - - providers.codegen_unit = |tcx, name| { - let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); - all.iter() - .find(|cgu| *cgu.name() == name) - .cloned() - .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) - }; - - provide_extern(providers); -} - -pub fn provide_extern(providers: &mut Providers) { +pub fn provide_both(providers: &mut Providers) { providers.dllimport_foreign_items = |tcx, krate| { let module_map = tcx.foreign_modules(krate); let module_map = module_map.iter() diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index f64cf0c7364dd..5d9bae5412e1a 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -192,13 +192,13 @@ impl CodegenBackend for LlvmCodegenBackend { fn provide(&self, providers: &mut ty::query::Providers) { rustc_codegen_utils::symbol_export::provide(providers); rustc_codegen_utils::symbol_names::provide(providers); - base::provide(providers); + base::provide_both(providers); attributes::provide(providers); } fn provide_extern(&self, providers: &mut ty::query::Providers) { rustc_codegen_utils::symbol_export::provide_extern(providers); - base::provide_extern(providers); + base::provide_both(providers); attributes::provide_extern(providers); } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 2f44dff2e22c3..ff21fc1ae3ee2 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -93,6 +93,7 @@ pub fn provide(providers: &mut Providers) { borrow_check::provide(providers); shim::provide(providers); transform::provide(providers); + monomorphize::partitioning::provide(providers); providers.const_eval = const_eval::const_eval_provider; providers.check_match = hair::pattern::check_match; } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 3a1108bb16983..940644ce20233 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -102,21 +102,27 @@ //! source-level module, functions from the same module will be available for //! inlining, even when they are not marked #[inline]. -use monomorphize::collector::InliningMap; +use std::collections::hash_map::Entry; +use std::cmp; +use std::sync::Arc; + +use syntax::ast::NodeId; +use syntax::symbol::InternedString; use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor}; use rustc::hir::CodegenFnAttrFlags; -use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::map::DefPathData; use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder}; use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; -use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use std::collections::hash_map::Entry; -use std::cmp; -use syntax::ast::NodeId; -use syntax::symbol::InternedString; +use rustc::ty::query::Providers; +use rustc::util::common::time; +use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet}; use rustc::mir::mono::MonoItem; + +use monomorphize::collector::InliningMap; +use monomorphize::collector::{self, MonoItemCollectionMode}; use monomorphize::item::{MonoItemExt, InstantiationMode}; pub use rustc::mir::mono::CodegenUnit; @@ -889,3 +895,146 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } } + +fn collect_and_partition_mono_items<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + cnum: CrateNum, +) -> (Arc, Arc>>>) +{ +assert_eq!(cnum, LOCAL_CRATE); + + let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items { + Some(ref s) => { + let mode_string = s.to_lowercase(); + let mode_string = mode_string.trim(); + if mode_string == "eager" { + MonoItemCollectionMode::Eager + } else { + if mode_string != "lazy" { + let message = format!("Unknown codegen-item collection mode '{}'. \ + Falling back to 'lazy' mode.", + mode_string); + tcx.sess.warn(&message); + } + + MonoItemCollectionMode::Lazy + } + } + None => { + if tcx.sess.opts.cg.link_dead_code { + MonoItemCollectionMode::Eager + } else { + MonoItemCollectionMode::Lazy + } + } + }; + + let (items, inlining_map) = + time(tcx.sess, "monomorphization collection", || { + collector::collect_crate_mono_items(tcx, collection_mode) + }); + + tcx.sess.abort_if_errors(); + + ::monomorphize::assert_symbols_are_distinct(tcx, items.iter()); + + let strategy = if tcx.sess.opts.incremental.is_some() { + PartitioningStrategy::PerModule + } else { + PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units()) + }; + + let codegen_units = time(tcx.sess, "codegen unit partitioning", || { + partition( + tcx, + items.iter().cloned(), + strategy, + &inlining_map + ) + .into_iter() + .map(Arc::new) + .collect::>() + }); + + let mono_items: DefIdSet = items.iter().filter_map(|mono_item| { + match *mono_item { + MonoItem::Fn(ref instance) => Some(instance.def_id()), + MonoItem::Static(def_id) => Some(def_id), + _ => None, + } + }).collect(); + + if tcx.sess.opts.debugging_opts.print_mono_items.is_some() { + let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default(); + + for cgu in &codegen_units { + for (&mono_item, &linkage) in cgu.items() { + item_to_cgus.entry(mono_item) + .or_default() + .push((cgu.name().clone(), linkage)); + } + } + + let mut item_keys: Vec<_> = items + .iter() + .map(|i| { + let mut output = i.to_string(tcx); + output.push_str(" @@"); + let mut empty = Vec::new(); + let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); + cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone()); + cgus.dedup(); + for &(ref cgu_name, (linkage, _)) in cgus.iter() { + output.push_str(" "); + output.push_str(&cgu_name.as_str()); + + let linkage_abbrev = match linkage { + Linkage::External => "External", + Linkage::AvailableExternally => "Available", + Linkage::LinkOnceAny => "OnceAny", + Linkage::LinkOnceODR => "OnceODR", + Linkage::WeakAny => "WeakAny", + Linkage::WeakODR => "WeakODR", + Linkage::Appending => "Appending", + Linkage::Internal => "Internal", + Linkage::Private => "Private", + Linkage::ExternalWeak => "ExternalWeak", + Linkage::Common => "Common", + }; + + output.push_str("["); + output.push_str(linkage_abbrev); + output.push_str("]"); + } + output + }) + .collect(); + + item_keys.sort(); + + for item in item_keys { + println!("MONO_ITEM {}", item); + } + } + + (Arc::new(mono_items), Arc::new(codegen_units)) +} + +pub fn provide(providers: &mut Providers) { + providers.collect_and_partition_mono_items = + collect_and_partition_mono_items; + + providers.is_codegened_item = |tcx, def_id| { + let (all_mono_items, _) = + tcx.collect_and_partition_mono_items(LOCAL_CRATE); + all_mono_items.contains(&def_id) + }; + + providers.codegen_unit = |tcx, name| { + let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); + all.iter() + .find(|cgu| *cgu.name() == name) + .cloned() + .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) + }; +} From 06695c2240d1f1af046cd2c31016d069dd319ba9 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 25 Oct 2018 15:11:59 +0200 Subject: [PATCH 18/33] Remove rustc_metadata_utils, which contains only one function --- src/Cargo.lock | 12 +------- src/librustc_codegen_utils/Cargo.toml | 2 +- src/librustc_codegen_utils/lib.rs | 2 +- src/librustc_codegen_utils/link.rs | 3 +- src/librustc_metadata/Cargo.toml | 1 - src/librustc_metadata/creader.rs | 4 +-- src/librustc_metadata/lib.rs | 31 ++++++++++++++++++- src/librustc_metadata_utils/Cargo.toml | 14 --------- src/librustc_metadata_utils/lib.rs | 42 -------------------------- 9 files changed, 35 insertions(+), 76 deletions(-) delete mode 100644 src/librustc_metadata_utils/Cargo.toml delete mode 100644 src/librustc_metadata_utils/lib.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 2b57883151f4e..dab67bc8d327e 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2138,7 +2138,7 @@ dependencies = [ "rustc_allocator 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", - "rustc_metadata_utils 0.0.0", + "rustc_metadata 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", @@ -2284,7 +2284,6 @@ dependencies = [ "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", - "rustc_metadata_utils 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -2292,15 +2291,6 @@ dependencies = [ "syntax_pos 0.0.0", ] -[[package]] -name = "rustc_metadata_utils" -version = "0.0.0" -dependencies = [ - "rustc 0.0.0", - "syntax 0.0.0", - "syntax_pos 0.0.0", -] - [[package]] name = "rustc_mir" version = "0.0.0" diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index 3a09e8e4b5606..4c57e97841409 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -20,6 +20,6 @@ rustc = { path = "../librustc" } rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } rustc_incremental = { path = "../librustc_incremental" } -rustc_metadata_utils = { path = "../librustc_metadata_utils" } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 89cf19d047216..f0ce1e9b0efab 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -35,12 +35,12 @@ extern crate serialize; extern crate rustc; extern crate rustc_allocator; extern crate rustc_target; +extern crate rustc_metadata; extern crate rustc_mir; extern crate rustc_incremental; extern crate syntax; extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; -extern crate rustc_metadata_utils; use std::path::PathBuf; diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index 2a1fbe6ace541..fa6d35f644d6f 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -13,7 +13,6 @@ use rustc::session::Session; use std::path::{Path, PathBuf}; use syntax::{ast, attr}; use syntax_pos::Span; -use rustc_metadata_utils::validate_crate_name; pub fn out_filename(sess: &Session, crate_type: config::CrateType, @@ -52,7 +51,7 @@ pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { let validate = |s: String, span: Option| { - validate_crate_name(sess, &s, span); + ::rustc_metadata::validate_crate_name(sess, &s, span); s }; diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 6142fe78149ce..338824d5efe4c 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -20,4 +20,3 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } -rustc_metadata_utils = { path = "../librustc_metadata_utils" } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 4b96735eb77b4..7733ab2e246d1 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -30,8 +30,6 @@ use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; -use rustc_metadata_utils::validate_crate_name; - use std::ops::Deref; use std::path::PathBuf; use std::{cmp, fs}; @@ -1106,7 +1104,7 @@ impl<'a> CrateLoader<'a> { item.ident, orig_name); let orig_name = match orig_name { Some(orig_name) => { - validate_crate_name(Some(self.sess), &orig_name.as_str(), + ::validate_crate_name(Some(self.sess), &orig_name.as_str(), Some(item.span)); orig_name } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 7008166b9035d..0cc0707a3a51f 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -38,7 +38,6 @@ extern crate serialize as rustc_serialize; // used by deriving extern crate rustc_errors as errors; extern crate syntax_ext; extern crate proc_macro; -extern crate rustc_metadata_utils; #[macro_use] extern crate rustc; @@ -64,4 +63,34 @@ pub mod cstore; pub mod dynamic_lib; pub mod locator; +pub fn validate_crate_name( + sess: Option<&rustc::session::Session>, + s: &str, + sp: Option +) { + let mut err_count = 0; + { + let mut say = |s: &str| { + match (sp, sess) { + (_, None) => bug!("{}", s), + (Some(sp), Some(sess)) => sess.span_err(sp, s), + (None, Some(sess)) => sess.err(s), + } + err_count += 1; + }; + if s.is_empty() { + say("crate name must not be empty"); + } + for c in s.chars() { + if c.is_alphanumeric() { continue } + if c == '_' { continue } + say(&format!("invalid character `{}` in crate name: `{}`", c, s)); + } + } + + if err_count > 0 { + sess.unwrap().abort_if_errors(); + } +} + __build_diagnostic_array! { librustc_metadata, DIAGNOSTICS } diff --git a/src/librustc_metadata_utils/Cargo.toml b/src/librustc_metadata_utils/Cargo.toml deleted file mode 100644 index 4a5e20376bfb5..0000000000000 --- a/src/librustc_metadata_utils/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rustc_metadata_utils" -version = "0.0.0" - -[lib] -name = "rustc_metadata_utils" -path = "lib.rs" -crate-type = ["dylib"] - -[dependencies] -rustc = { path = "../librustc" } -syntax = { path = "../libsyntax" } -syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_metadata_utils/lib.rs b/src/librustc_metadata_utils/lib.rs deleted file mode 100644 index a1e5150390ac1..0000000000000 --- a/src/librustc_metadata_utils/lib.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[macro_use] -extern crate rustc; -extern crate syntax_pos; - -use rustc::session::Session; -use syntax_pos::Span; - -pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { - let mut err_count = 0; - { - let mut say = |s: &str| { - match (sp, sess) { - (_, None) => bug!("{}", s), - (Some(sp), Some(sess)) => sess.span_err(sp, s), - (None, Some(sess)) => sess.err(s), - } - err_count += 1; - }; - if s.is_empty() { - say("crate name must not be empty"); - } - for c in s.chars() { - if c.is_alphanumeric() { continue } - if c == '_' { continue } - say(&format!("invalid character `{}` in crate name: `{}`", c, s)); - } - } - - if err_count > 0 { - sess.unwrap().abort_if_errors(); - } -} From adafd0f9a0410a9c5d2aea3a36559a2f1d84da34 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 25 Oct 2018 18:04:54 +0200 Subject: [PATCH 19/33] Fix indentation --- src/librustc_mir/monomorphize/partitioning.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 940644ce20233..03811cd9949e3 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -901,7 +901,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( cnum: CrateNum, ) -> (Arc, Arc>>>) { -assert_eq!(cnum, LOCAL_CRATE); + assert_eq!(cnum, LOCAL_CRATE); let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items { Some(ref s) => { From 8d5fb4c9554a3e1713f10db25deed41fbc2d4c7c Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 18 Oct 2018 19:09:49 +0200 Subject: [PATCH 20/33] Add note linking to Rust 2018 path semantics docs. This commit extends existing path suggestions to link to documentation on the changed semantics of `use` in Rust 2018. --- src/librustc_resolve/error_reporting.rs | 25 ++++--- src/librustc_resolve/resolve_imports.rs | 65 +++++++++++++------ .../local-path-suggestions-2018.stderr | 2 + 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index d77b1868ed72e..52848fbb3b112 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -24,7 +24,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); // If we don't have a path to suggest changes to, then return. if path.is_empty() { @@ -60,13 +60,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = keywords::SelfValue.name(); let result = self.resolve_path(None, &path, None, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some((path, None)) } else { None } @@ -83,13 +83,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Crate.name(); let result = self.resolve_path(None, &path, None, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some(( + path, + Some( + "`use` statements changed in Rust 2018; read more at \ + ".to_string() + ), + )) } else { None } @@ -106,13 +113,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Super.name(); let result = self.resolve_path(None, &path, None, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some((path, None)) } else { None } @@ -132,7 +139,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Need to clone else we can't call `resolve_path` without a borrow error. We also store // into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic) // each time. @@ -153,7 +160,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); if let PathResult::Module(..) = result { - return Some(path) + return Some((path, None)); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 810aff7f9b0a8..85686c03c2da8 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -703,7 +703,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } }); - } else if let Some((span, err)) = error { + } else if let Some((span, err, note)) = error { errors = true; if let SingleImport { source, ref result, .. } = import.subclass { @@ -733,7 +733,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &import.subclass, span, ); - error_vec.push((span, path, err)); + error_vec.push((span, path, err, note)); seen_spans.insert(span); prev_root_id = import.root_id; } @@ -825,27 +825,45 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } - fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>, - span: Option) { + fn throw_unresolved_import_error( + &self, + error_vec: Vec<(Span, String, String, Option)>, + span: Option, + ) { let max_span_label_msg_count = 10; // upper limit on number of span_label message. - let (span, msg) = if error_vec.is_empty() { - (span.unwrap(), "unresolved import".to_string()) + let (span, msg, note) = if error_vec.is_empty() { + (span.unwrap(), "unresolved import".to_string(), None) } else { - let span = MultiSpan::from_spans(error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { elem.0 }) - .collect()); + let span = MultiSpan::from_spans( + error_vec.clone().into_iter() + .map(|elem: (Span, String, String, Option)| elem.0) + .collect() + ); + + let note: Option = error_vec.clone().into_iter() + .filter_map(|elem: (Span, String, String, Option)| elem.3) + .last(); + let path_vec: Vec = error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) }) + .map(|elem: (Span, String, String, Option)| format!("`{}`", elem.1)) .collect(); let path = path_vec.join(", "); - let msg = format!("unresolved import{} {}", - if path_vec.len() > 1 { "s" } else { "" }, path); - (span, msg) + let msg = format!( + "unresolved import{} {}", + if path_vec.len() > 1 { "s" } else { "" }, + path + ); + + (span, msg, note) }; + let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg); for span_error in error_vec.into_iter().take(max_span_label_msg_count) { err.span_label(span_error.0, span_error.2); } + if let Some(note) = note { + err.note(¬e); + } err.emit(); } @@ -941,7 +959,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } // If appropriate, returns an error to report. - fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { + fn finalize_import( + &mut self, + directive: &'b ImportDirective<'b> + ) -> Option<(Span, String, Option)> { self.current_module = directive.parent; let ImportDirective { ref module_path, span, .. } = *directive; @@ -964,15 +985,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { return None; } PathResult::Failed(span, msg, true) => { - return if let Some(suggested_path) = self.make_path_suggestion( + return if let Some((suggested_path, note)) = self.make_path_suggestion( span, module_path.clone() ) { Some(( span, - format!("Did you mean `{}`?", Segment::names_to_string(&suggested_path)) + format!("Did you mean `{}`?", Segment::names_to_string(&suggested_path)), + note, )) } else { - Some((span, msg)) + Some((span, msg, None)) }; }, _ => return None, @@ -997,8 +1019,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { if let ModuleOrUniformRoot::Module(module) = module { if module.def_id() == directive.parent.def_id() { // Importing a module into itself is not allowed. - return Some((directive.span, - "Cannot glob-import a module into itself.".to_string())); + return Some(( + directive.span, + "Cannot glob-import a module into itself.".to_string(), + None, + )); } } if !is_prelude && @@ -1096,7 +1121,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } }; - Some((span, msg)) + Some((span, msg, None)) } else { // `resolve_ident_in_module` reported a privacy error. self.import_dummy_binding(directive); diff --git a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr index 97bf748881f29..2293f4b001749 100644 --- a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr +++ b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr @@ -3,6 +3,8 @@ error[E0432]: unresolved import `foo` | LL | use foo::Bar; | ^^^ Did you mean `crate::foo`? + | + = note: `use` statements changed in Rust 2018; read more at error[E0432]: unresolved import `foo` --> $DIR/local-path-suggestions-2018.rs:27:5 From c674802aac1a8d8cc3e78938a192067617aa286e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Tue, 23 Oct 2018 19:59:18 +0200 Subject: [PATCH 21/33] Remove unnecessary mut in iterator.find_map documentation example, Relates to #49098 --- src/libcore/iter/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 5b6d9e2033caa..2903c370df898 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1857,7 +1857,7 @@ pub trait Iterator { /// ``` /// let a = ["lol", "NaN", "2", "5"]; /// - /// let mut first_number = a.iter().find_map(|s| s.parse().ok()); + /// let first_number = a.iter().find_map(|s| s.parse().ok()); /// /// assert_eq!(first_number, Some(2)); /// ``` From bb37f1820af64d1367cf19670bff00bef34bd7c4 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Oct 2018 15:45:03 +0200 Subject: [PATCH 22/33] Turn ICE for dangling pointers into error --- src/librustc_mir/interpret/memory.rs | 5 +++++ src/test/ui/consts/dangling-alloc-id-ice.rs | 15 +++++++++++++++ src/test/ui/consts/dangling-alloc-id-ice.stderr | 13 +++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/test/ui/consts/dangling-alloc-id-ice.rs create mode 100644 src/test/ui/consts/dangling-alloc-id-ice.stderr diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index ff3fdffcd7622..4d755bf90b370 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -737,6 +737,11 @@ where if self.alloc_map.contains_key(&alloc) { // Not yet interned, so proceed recursively self.intern_static(alloc, mutability)?; + } else if self.dead_alloc_map.contains_key(&alloc) { + // danging pointer + return err!(ValidationFailure( + "encountered dangling pointer in final constant".into(), + )) } } Ok(()) diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs new file mode 100644 index 0000000000000..31fa23ae23221 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/55223 + +#![feature(const_let)] + +union Foo<'a> { + y: &'a (), + long_live_the_unit: &'static (), +} + +const FOO: &() = { //~ ERROR this constant cannot be used + let y = (); + unsafe { Foo { y: &y }.long_live_the_unit } +}; + +fn main() {} diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr new file mode 100644 index 0000000000000..df623f943addc --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -0,0 +1,13 @@ +error: this constant cannot be used + --> $DIR/dangling-alloc-id-ice.rs:10:1 + | +LL | / const FOO: &() = { //~ ERROR this constant cannot be used +LL | | let y = (); +LL | | unsafe { Foo { y: &y }.long_live_the_unit } +LL | | }; + | |__^ type validation failed: encountered dangling pointer in final constant + | + = note: #[deny(const_err)] on by default + +error: aborting due to previous error + From caabc72c3324c5fb818c480d6ed407f2e6f82473 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Oct 2018 18:05:27 +0200 Subject: [PATCH 23/33] Reproduce the underlying issue nll (and thus the algorithm for actual promotion) don't know about some casts anymore --- .../consts/dangling-alloc-id-ice-2.nll.stderr | 30 +++++++++++++++++++ src/test/ui/consts/dangling-alloc-id-ice-2.rs | 10 +++++++ .../ui/consts/dangling-alloc-id-ice-2.stderr | 11 +++++++ 3 files changed, 51 insertions(+) create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.rs create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.stderr diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr b/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr new file mode 100644 index 0000000000000..e6ae57796055f --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr @@ -0,0 +1,30 @@ +warning[E0716]: temporary value dropped while borrowed + --> $DIR/dangling-alloc-id-ice-2.rs:5:28 + | +LL | static MAP: Slice = Slice(&[ + | ___________________________-^ + | |___________________________| + | || +LL | || b"CloseEvent" as &'static [u8], +LL | || ]); + | || -- temporary value is freed at the end of this statement + | ||_| + | |__creates a temporary which is freed while still in use + | cast requires that borrow lasts for `'static` + | + = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. + It represents potential unsoundness in your code. + This warning will become a hard error in the future. + +error[E0080]: could not evaluate static initializer + --> $DIR/dangling-alloc-id-ice-2.rs:5:1 + | +LL | / static MAP: Slice = Slice(&[ +LL | | b"CloseEvent" as &'static [u8], +LL | | ]); + | |___^ type validation failed: encountered dangling pointer in final constant + +error: aborting due to previous error + +Some errors occurred: E0080, E0716. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.rs b/src/test/ui/consts/dangling-alloc-id-ice-2.rs new file mode 100644 index 0000000000000..9af72c8dc0b83 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.rs @@ -0,0 +1,10 @@ +// https://github.com/rust-lang/rust/issues/55223 + +struct Slice(&'static [&'static [u8]]); + +static MAP: Slice = Slice(&[ + b"CloseEvent" as &'static [u8], +]); + + +fn main() {} diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.stderr b/src/test/ui/consts/dangling-alloc-id-ice-2.stderr new file mode 100644 index 0000000000000..42df542f55cf5 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.stderr @@ -0,0 +1,11 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/dangling-alloc-id-ice-2.rs:5:1 + | +LL | / static MAP: Slice = Slice(&[ +LL | | b"CloseEvent" as &'static [u8], +LL | | ]); + | |___^ type validation failed: encountered dangling pointer in final constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 7a2879f7b659886747ceba570d2bc2b0b0d97c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Tue, 23 Oct 2018 13:39:30 +0200 Subject: [PATCH 24/33] Update dangling-alloc-id-ice-2.rs --- src/test/ui/consts/dangling-alloc-id-ice-2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.rs b/src/test/ui/consts/dangling-alloc-id-ice-2.rs index 9af72c8dc0b83..b4691641fc98f 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice-2.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.rs @@ -1,4 +1,4 @@ -// https://github.com/rust-lang/rust/issues/55223 +// FIXME(#55223) this is just a reproduction test showing the wrong behavior struct Slice(&'static [&'static [u8]]); From 9d189689af9d406ef6400065244cb06177dc1809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Wed, 24 Oct 2018 20:34:34 +0200 Subject: [PATCH 25/33] Typo --- src/librustc_mir/interpret/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 4d755bf90b370..f073ae95678ac 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -738,7 +738,7 @@ where // Not yet interned, so proceed recursively self.intern_static(alloc, mutability)?; } else if self.dead_alloc_map.contains_key(&alloc) { - // danging pointer + // dangling pointer return err!(ValidationFailure( "encountered dangling pointer in final constant".into(), )) From 5c45fef6d098c827df9c7ab24ebe38f7e481e9ac Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 26 Oct 2018 17:51:58 +0200 Subject: [PATCH 26/33] Update and add new test (fixes #55353) --- src/test/ui/consts/dangling-alloc-id-ice.rs | 2 +- src/test/ui/consts/dangling-alloc-id-ice.stderr | 4 ++-- src/test/ui/consts/dangling_raw_ptr.rs | 10 ++++++++++ src/test/ui/consts/dangling_raw_ptr.stderr | 13 +++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/dangling_raw_ptr.rs create mode 100644 src/test/ui/consts/dangling_raw_ptr.stderr diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs index 31fa23ae23221..695d33b690898 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -7,7 +7,7 @@ union Foo<'a> { long_live_the_unit: &'static (), } -const FOO: &() = { //~ ERROR this constant cannot be used +const FOO: &() = { //~ ERROR any use of this value will cause an error let y = (); unsafe { Foo { y: &y }.long_live_the_unit } }; diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index df623f943addc..a5fa88e5e6832 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -1,7 +1,7 @@ -error: this constant cannot be used +error: any use of this value will cause an error --> $DIR/dangling-alloc-id-ice.rs:10:1 | -LL | / const FOO: &() = { //~ ERROR this constant cannot be used +LL | / const FOO: &() = { //~ ERROR any use of this value will cause an error LL | | let y = (); LL | | unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; diff --git a/src/test/ui/consts/dangling_raw_ptr.rs b/src/test/ui/consts/dangling_raw_ptr.rs new file mode 100644 index 0000000000000..86c9787f81fc5 --- /dev/null +++ b/src/test/ui/consts/dangling_raw_ptr.rs @@ -0,0 +1,10 @@ +#![feature(const_let)] + +const FOO: *const u32 = { //~ ERROR any use of this value will cause an error + let x = 42; + &x +}; + +fn main() { + let x = FOO; +} \ No newline at end of file diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr new file mode 100644 index 0000000000000..3b20936f8ae97 --- /dev/null +++ b/src/test/ui/consts/dangling_raw_ptr.stderr @@ -0,0 +1,13 @@ +error: any use of this value will cause an error + --> $DIR/dangling_raw_ptr.rs:3:1 + | +LL | / const FOO: *const u32 = { //~ ERROR any use of this value will cause an error +LL | | let x = 42; +LL | | &x +LL | | }; + | |__^ type validation failed: encountered dangling pointer in final constant + | + = note: #[deny(const_err)] on by default + +error: aborting due to previous error + From 599eb1253c5fe2647e27ddea3efcd9d5ee363035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Fri, 26 Oct 2018 19:04:13 +0200 Subject: [PATCH 27/33] Add trailing newline --- src/test/ui/consts/dangling_raw_ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/dangling_raw_ptr.rs b/src/test/ui/consts/dangling_raw_ptr.rs index 86c9787f81fc5..7fc773412f2f8 100644 --- a/src/test/ui/consts/dangling_raw_ptr.rs +++ b/src/test/ui/consts/dangling_raw_ptr.rs @@ -7,4 +7,4 @@ const FOO: *const u32 = { //~ ERROR any use of this value will cause an error fn main() { let x = FOO; -} \ No newline at end of file +} From 4cb611f3d1287526b99e9de93f7f034ab60947cd Mon Sep 17 00:00:00 2001 From: Hsiang-Cheng Yang Date: Sat, 27 Oct 2018 14:33:07 +0800 Subject: [PATCH 28/33] Update string.rs remove unused variable i in example String::with_capacity() --- src/liballoc/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index ab3f8fc270720..ff3587d5d8730 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -413,7 +413,7 @@ impl String { /// /// // These are all done without reallocating... /// let cap = s.capacity(); - /// for i in 0..10 { + /// for _ in 0..10 { /// s.push('a'); /// } /// From c04893afbb1bccc2ceeccdd7b7f46e5cb5dc126d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 27 Oct 2018 13:34:35 +0200 Subject: [PATCH 29/33] Fix an ICE in the min_const_fn analysis --- .../transform/qualify_min_const_fn.rs | 5 +++-- src/test/ui/consts/single_variant_match_ice.rs | 15 +++++++++++++++ .../ui/consts/single_variant_match_ice.stderr | 8 ++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/single_variant_match_ice.rs create mode 100644 src/test/ui/consts/single_variant_match_ice.stderr diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 52c557b83d591..6ab68789c027b 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -317,7 +317,8 @@ fn check_terminator( check_place(tcx, mir, location, span, PlaceMode::Read)?; check_operand(tcx, mir, value, span) }, - TerminatorKind::SwitchInt { .. } => Err(( + + TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err(( span, "`if`, `match`, `&&` and `||` are not stable in const fn".into(), )), @@ -363,7 +364,7 @@ fn check_terminator( cleanup: _, } => check_operand(tcx, mir, cond, span), - | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!( + | TerminatorKind::FalseUnwind { .. } => span_bug!( terminator.source_info.span, "min_const_fn encountered `{:#?}`", terminator diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs new file mode 100644 index 0000000000000..67a41bc5dc4ad --- /dev/null +++ b/src/test/ui/consts/single_variant_match_ice.rs @@ -0,0 +1,15 @@ +enum Foo { + Prob, +} + +impl Foo { + pub const fn as_val(&self) -> u8 { + use self::Foo::*; + + match *self { + Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn + } + } +} + +fn main() {} diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr new file mode 100644 index 0000000000000..a0222b0d489a4 --- /dev/null +++ b/src/test/ui/consts/single_variant_match_ice.stderr @@ -0,0 +1,8 @@ +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/single_variant_match_ice.rs:10:13 + | +LL | Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn + | ^^^^ + +error: aborting due to previous error + From 630c6a544f91a29f2a1749dd438e7082400295da Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 29 Sep 2018 17:25:26 -0700 Subject: [PATCH 30/33] introducing lint reason annotations (RFC 2383) This is just for the `reason =` name-value meta-item; the `#[expect(lint)]` attribute also described in the RFC is a problem for another day. The place where we were directly calling `emit()` on a match block (whose arms returned a mutable reference to a diagnostic-builder) was admittedly cute, but no longer plausibly natural after adding the if-let to the end of the `LintSource::Node` arm. This regards #54503. --- src/librustc/lint/levels.rs | 69 +++++++++++++++++------ src/librustc/lint/mod.rs | 9 ++- src/test/ui/lint/reasons-erroneous.rs | 16 ++++++ src/test/ui/lint/reasons-erroneous.stderr | 45 +++++++++++++++ src/test/ui/lint/reasons-forbidden.rs | 19 +++++++ src/test/ui/lint/reasons-forbidden.stderr | 14 +++++ src/test/ui/lint/reasons.rs | 31 ++++++++++ src/test/ui/lint/reasons.stderr | 28 +++++++++ 8 files changed, 211 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/lint/reasons-erroneous.rs create mode 100644 src/test/ui/lint/reasons-erroneous.stderr create mode 100644 src/test/ui/lint/reasons-forbidden.rs create mode 100644 src/test/ui/lint/reasons-forbidden.stderr create mode 100644 src/test/ui/lint/reasons.rs create mode 100644 src/test/ui/lint/reasons.stderr diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 6a4f734674563..86d0a5a479006 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -199,8 +199,7 @@ impl<'a> LintLevelsBuilder<'a> { let store = self.sess.lint_store.borrow(); let sess = self.sess; let bad_attr = |span| { - span_err!(sess, span, E0452, - "malformed lint attribute"); + struct_span_err!(sess, span, E0452, "malformed lint attribute") }; for attr in attrs { let level = match Level::from_str(&attr.name().as_str()) { @@ -214,17 +213,45 @@ impl<'a> LintLevelsBuilder<'a> { let metas = if let Some(metas) = meta.meta_item_list() { metas } else { - bad_attr(meta.span); + let mut err = bad_attr(meta.span); + err.emit(); continue }; + // Before processing the lint names, look for a reason (RFC 2383). + let mut reason = None; + for li in metas { + if let Some(item) = li.meta_item() { + match item.node { + ast::MetaItemKind::Word => {} // actual lint names handled later + ast::MetaItemKind::NameValue(ref name_value) => { + let name_ident = item.ident.segments[0].ident; + let name = name_ident.name.as_str(); + if name == "reason" { + if let ast::LitKind::Str(rationale, _) = name_value.node { + reason = Some(rationale); + } else { + let mut err = bad_attr(name_value.span); + err.help("reason must be a string literal"); + err.emit(); + } + } else { + let mut err = bad_attr(item.span); + err.emit(); + } + }, + ast::MetaItemKind::List(_) => { + let mut err = bad_attr(item.span); + err.emit(); + } + } + } + } + for li in metas { let word = match li.word() { Some(word) => word, - None => { - bad_attr(li.span); - continue - } + None => { continue; } }; let tool_name = if let Some(lint_tool) = word.is_scoped() { if !attr::is_known_lint_tool(lint_tool) { @@ -245,7 +272,7 @@ impl<'a> LintLevelsBuilder<'a> { let name = word.name(); match store.check_lint_name(&name.as_str(), tool_name) { CheckLintNameResult::Ok(ids) => { - let src = LintSource::Node(name, li.span); + let src = LintSource::Node(name, li.span, reason); for id in ids { specs.insert(*id, (level, src)); } @@ -255,7 +282,9 @@ impl<'a> LintLevelsBuilder<'a> { match result { Ok(ids) => { let complete_name = &format!("{}::{}", tool_name.unwrap(), name); - let src = LintSource::Node(Symbol::intern(complete_name), li.span); + let src = LintSource::Node( + Symbol::intern(complete_name), li.span, reason + ); for id in ids { specs.insert(*id, (level, src)); } @@ -286,7 +315,9 @@ impl<'a> LintLevelsBuilder<'a> { Applicability::MachineApplicable, ).emit(); - let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span); + let src = LintSource::Node( + Symbol::intern(&new_lint_name), li.span, reason + ); for id in ids { specs.insert(*id, (level, src)); } @@ -368,11 +399,11 @@ impl<'a> LintLevelsBuilder<'a> { }; let forbidden_lint_name = match forbid_src { LintSource::Default => id.to_string(), - LintSource::Node(name, _) => name.to_string(), + LintSource::Node(name, _, _) => name.to_string(), LintSource::CommandLine(name) => name.to_string(), }; let (lint_attr_name, lint_attr_span) = match *src { - LintSource::Node(name, span) => (name, span), + LintSource::Node(name, span, _) => (name, span), _ => continue, }; let mut diag_builder = struct_span_err!(self.sess, @@ -384,15 +415,19 @@ impl<'a> LintLevelsBuilder<'a> { forbidden_lint_name); diag_builder.span_label(lint_attr_span, "overruled by previous forbid"); match forbid_src { - LintSource::Default => &mut diag_builder, - LintSource::Node(_, forbid_source_span) => { + LintSource::Default => {}, + LintSource::Node(_, forbid_source_span, reason) => { diag_builder.span_label(forbid_source_span, - "`forbid` level set here") + "`forbid` level set here"); + if let Some(rationale) = reason { + diag_builder.note(&rationale.as_str()); + } }, LintSource::CommandLine(_) => { - diag_builder.note("`forbid` lint level was set on command line") + diag_builder.note("`forbid` lint level was set on command line"); } - }.emit(); + } + diag_builder.emit(); // don't set a separate error for every lint in the group break } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5ac0c0d32dcdc..afd7800810982 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -470,7 +470,7 @@ pub enum LintSource { Default, /// Lint level was set by an attribute. - Node(ast::Name, Span), + Node(ast::Name, Span, Option /* RFC 2383 reason */), /// Lint level was set by a command-line flag. CommandLine(Symbol), @@ -478,7 +478,7 @@ pub enum LintSource { impl_stable_hash_for!(enum self::LintSource { Default, - Node(name, span), + Node(name, span, reason), CommandLine(text) }); @@ -578,7 +578,10 @@ pub fn struct_lint_level<'a>(sess: &'a Session, hyphen_case_flag_val)); } } - LintSource::Node(lint_attr_name, src) => { + LintSource::Node(lint_attr_name, src, reason) => { + if let Some(rationale) = reason { + err.note(&rationale.as_str()); + } sess.diag_span_note_once(&mut err, DiagnosticMessageId::from(lint), src, "lint level defined here"); if lint_attr_name.as_str() != name { diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs new file mode 100644 index 0000000000000..68f2ce42847d7 --- /dev/null +++ b/src/test/ui/lint/reasons-erroneous.rs @@ -0,0 +1,16 @@ +#![warn(absolute_paths_not_starting_with_crate, reason = 0)] +//~^ ERROR malformed lint attribute +//~| HELP reason must be a string literal +#![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] +//~^ ERROR malformed lint attribute +//~| HELP reason must be a string literal +#![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] +//~^ ERROR malformed lint attribute +#![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] +//~^ ERROR malformed lint attribute +#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] +//~^ ERROR malformed lint attribute +#![warn(ellipsis_inclusive_range_patterns, reason)] +//~^ WARN unknown lint + +fn main() {} diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr new file mode 100644 index 0000000000000..25bdda178eee0 --- /dev/null +++ b/src/test/ui/lint/reasons-erroneous.stderr @@ -0,0 +1,45 @@ +error[E0452]: malformed lint attribute + --> $DIR/reasons-erroneous.rs:1:58 + | +LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] + | ^ + | + = help: reason must be a string literal + +error[E0452]: malformed lint attribute + --> $DIR/reasons-erroneous.rs:4:40 + | +LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: reason must be a string literal + +error[E0452]: malformed lint attribute + --> $DIR/reasons-erroneous.rs:7:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0452]: malformed lint attribute + --> $DIR/reasons-erroneous.rs:9:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0452]: malformed lint attribute + --> $DIR/reasons-erroneous.rs:11:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unknown lint: `reason` + --> $DIR/reasons-erroneous.rs:13:44 + | +LL | #![warn(ellipsis_inclusive_range_patterns, reason)] + | ^^^^^^ + | + = note: #[warn(unknown_lints)] on by default + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0452`. diff --git a/src/test/ui/lint/reasons-forbidden.rs b/src/test/ui/lint/reasons-forbidden.rs new file mode 100644 index 0000000000000..cad62b3a3c16c --- /dev/null +++ b/src/test/ui/lint/reasons-forbidden.rs @@ -0,0 +1,19 @@ +#![forbid( + unsafe_code, + //~^ NOTE `forbid` level set here + reason = "our errors & omissions insurance policy doesn't cover unsafe Rust" +)] + +use std::ptr; + +fn main() { + let a_billion_dollar_mistake = ptr::null(); + + #[allow(unsafe_code)] + //~^ ERROR allow(unsafe_code) overruled by outer forbid(unsafe_code) + //~| NOTE overruled by previous forbid + //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust + unsafe { + *a_billion_dollar_mistake + } +} diff --git a/src/test/ui/lint/reasons-forbidden.stderr b/src/test/ui/lint/reasons-forbidden.stderr new file mode 100644 index 0000000000000..cc9e787b2d42d --- /dev/null +++ b/src/test/ui/lint/reasons-forbidden.stderr @@ -0,0 +1,14 @@ +error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code) + --> $DIR/reasons-forbidden.rs:12:13 + | +LL | unsafe_code, + | ----------- `forbid` level set here +... +LL | #[allow(unsafe_code)] + | ^^^^^^^^^^^ overruled by previous forbid + | + = note: our errors & omissions insurance policy doesn't cover unsafe Rust + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0453`. diff --git a/src/test/ui/lint/reasons.rs b/src/test/ui/lint/reasons.rs new file mode 100644 index 0000000000000..9166caf9ebec6 --- /dev/null +++ b/src/test/ui/lint/reasons.rs @@ -0,0 +1,31 @@ +// compile-pass + +#![warn(elided_lifetimes_in_paths, + //~^ NOTE lint level defined here + reason = "explicit anonymous lifetimes aid reasoning about ownership")] +#![warn( + nonstandard_style, + //~^ NOTE lint level defined here + reason = r#"people shouldn't have to change their usual style habits +to contribute to our project"# +)] +#![allow(unused, reason = "unused code has never killed anypony")] + +use std::fmt; + +pub struct CheaterDetectionMechanism {} + +impl fmt::Debug for CheaterDetectionMechanism { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + //~^ WARN hidden lifetime parameters in types are deprecated + //~| NOTE explicit anonymous lifetimes aid + //~| HELP indicate the anonymous lifetime + fmt.debug_struct("CheaterDetectionMechanism").finish() + } +} + +fn main() { + let Social_exchange_psychology = CheaterDetectionMechanism {}; + //~^ WARN should have a snake case name such as + //~| NOTE people shouldn't have to change their usual style habits +} diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr new file mode 100644 index 0000000000000..bdaf848c340e3 --- /dev/null +++ b/src/test/ui/lint/reasons.stderr @@ -0,0 +1,28 @@ +warning: hidden lifetime parameters in types are deprecated + --> $DIR/reasons.rs:19:29 + | +LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + | ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` + | + = note: explicit anonymous lifetimes aid reasoning about ownership +note: lint level defined here + --> $DIR/reasons.rs:3:9 + | +LL | #![warn(elided_lifetimes_in_paths, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: variable `Social_exchange_psychology` should have a snake case name such as `social_exchange_psychology` + --> $DIR/reasons.rs:28:9 + | +LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: people shouldn't have to change their usual style habits + to contribute to our project +note: lint level defined here + --> $DIR/reasons.rs:7:5 + | +LL | nonstandard_style, + | ^^^^^^^^^^^^^^^^^ + = note: #[warn(non_snake_case)] implied by #[warn(nonstandard_style)] + From dc0609c2473c01f521c5a3b9959edf7dd11f2d86 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 29 Sep 2018 18:00:50 -0700 Subject: [PATCH 31/33] feature-gate lint reasons We take stability seriously, so we shy away from making even seemingly "trivial" features insta-stable. --- src/librustc/lint/levels.rs | 14 +++++++++++++- src/libsyntax/feature_gate.rs | 3 +++ .../ui/feature-gates/feature-gate-lint-reasons.rs | 4 ++++ .../feature-gates/feature-gate-lint-reasons.stderr | 11 +++++++++++ src/test/ui/lint/reasons-erroneous.rs | 2 ++ src/test/ui/lint/reasons-erroneous.stderr | 12 ++++++------ src/test/ui/lint/reasons-forbidden.rs | 2 ++ src/test/ui/lint/reasons-forbidden.stderr | 2 +- src/test/ui/lint/reasons.rs | 2 ++ src/test/ui/lint/reasons.stderr | 8 ++++---- 10 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-lint-reasons.rs create mode 100644 src/test/ui/feature-gates/feature-gate-lint-reasons.stderr diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 86d0a5a479006..ee878da00660e 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -225,11 +225,23 @@ impl<'a> LintLevelsBuilder<'a> { match item.node { ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { + let gate_reasons = !self.sess.features_untracked().lint_reasons; let name_ident = item.ident.segments[0].ident; let name = name_ident.name.as_str(); + if name == "reason" { if let ast::LitKind::Str(rationale, _) = name_value.node { - reason = Some(rationale); + if gate_reasons { + feature_gate::emit_feature_err( + &self.sess.parse_sess, + "lint_reasons", + item.span, + feature_gate::GateIssue::Language, + "lint reasons are experimental" + ); + } else { + reason = Some(rationale); + } } else { let mut err = bad_attr(name_value.span); err.help("reason must be a string literal"); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2cd4fd92bc81e..da0ec33030e06 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -504,6 +504,9 @@ declare_features! ( // `extern crate foo as bar;` puts `bar` into extern prelude. (active, extern_crate_item_prelude, "1.31.0", Some(54658), None), + + // `reason = ` in lint attributes and `expect` lint attribute + (active, lint_reasons, "1.31.0", Some(54503), None), ); declare_features! ( diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.rs b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs new file mode 100644 index 0000000000000..1a7b9c990fa64 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.rs @@ -0,0 +1,4 @@ +#![warn(nonstandard_style, reason = "the standard should be respected")] +//~^ ERROR lint reasons are experimental + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr new file mode 100644 index 0000000000000..6a36d9fd5a8e5 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-lint-reasons.stderr @@ -0,0 +1,11 @@ +error[E0658]: lint reasons are experimental (see issue #54503) + --> $DIR/feature-gate-lint-reasons.rs:1:28 + | +LL | #![warn(nonstandard_style, reason = "the standard should be respected")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(lint_reasons)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs index 68f2ce42847d7..90111a9c4e1e9 100644 --- a/src/test/ui/lint/reasons-erroneous.rs +++ b/src/test/ui/lint/reasons-erroneous.rs @@ -1,3 +1,5 @@ +#![feature(lint_reasons)] + #![warn(absolute_paths_not_starting_with_crate, reason = 0)] //~^ ERROR malformed lint attribute //~| HELP reason must be a string literal diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr index 25bdda178eee0..f66999e927203 100644 --- a/src/test/ui/lint/reasons-erroneous.stderr +++ b/src/test/ui/lint/reasons-erroneous.stderr @@ -1,5 +1,5 @@ error[E0452]: malformed lint attribute - --> $DIR/reasons-erroneous.rs:1:58 + --> $DIR/reasons-erroneous.rs:3:58 | LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] | ^ @@ -7,7 +7,7 @@ LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] = help: reason must be a string literal error[E0452]: malformed lint attribute - --> $DIR/reasons-erroneous.rs:4:40 + --> $DIR/reasons-erroneous.rs:6:40 | LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,25 +15,25 @@ LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condem = help: reason must be a string literal error[E0452]: malformed lint attribute - --> $DIR/reasons-erroneous.rs:7:29 + --> $DIR/reasons-erroneous.rs:9:29 | LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0452]: malformed lint attribute - --> $DIR/reasons-erroneous.rs:9:23 + --> $DIR/reasons-erroneous.rs:11:23 | LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0452]: malformed lint attribute - --> $DIR/reasons-erroneous.rs:11:36 + --> $DIR/reasons-erroneous.rs:13:36 | LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unknown lint: `reason` - --> $DIR/reasons-erroneous.rs:13:44 + --> $DIR/reasons-erroneous.rs:15:44 | LL | #![warn(ellipsis_inclusive_range_patterns, reason)] | ^^^^^^ diff --git a/src/test/ui/lint/reasons-forbidden.rs b/src/test/ui/lint/reasons-forbidden.rs index cad62b3a3c16c..19ab76707d408 100644 --- a/src/test/ui/lint/reasons-forbidden.rs +++ b/src/test/ui/lint/reasons-forbidden.rs @@ -1,3 +1,5 @@ +#![feature(lint_reasons)] + #![forbid( unsafe_code, //~^ NOTE `forbid` level set here diff --git a/src/test/ui/lint/reasons-forbidden.stderr b/src/test/ui/lint/reasons-forbidden.stderr index cc9e787b2d42d..ea09e591cba0f 100644 --- a/src/test/ui/lint/reasons-forbidden.stderr +++ b/src/test/ui/lint/reasons-forbidden.stderr @@ -1,5 +1,5 @@ error[E0453]: allow(unsafe_code) overruled by outer forbid(unsafe_code) - --> $DIR/reasons-forbidden.rs:12:13 + --> $DIR/reasons-forbidden.rs:14:13 | LL | unsafe_code, | ----------- `forbid` level set here diff --git a/src/test/ui/lint/reasons.rs b/src/test/ui/lint/reasons.rs index 9166caf9ebec6..eba91d92afb5b 100644 --- a/src/test/ui/lint/reasons.rs +++ b/src/test/ui/lint/reasons.rs @@ -1,5 +1,7 @@ // compile-pass +#![feature(lint_reasons)] + #![warn(elided_lifetimes_in_paths, //~^ NOTE lint level defined here reason = "explicit anonymous lifetimes aid reasoning about ownership")] diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr index bdaf848c340e3..df0f9cb9b61e8 100644 --- a/src/test/ui/lint/reasons.stderr +++ b/src/test/ui/lint/reasons.stderr @@ -1,18 +1,18 @@ warning: hidden lifetime parameters in types are deprecated - --> $DIR/reasons.rs:19:29 + --> $DIR/reasons.rs:21:29 | LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ^^^^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` | = note: explicit anonymous lifetimes aid reasoning about ownership note: lint level defined here - --> $DIR/reasons.rs:3:9 + --> $DIR/reasons.rs:5:9 | LL | #![warn(elided_lifetimes_in_paths, | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: variable `Social_exchange_psychology` should have a snake case name such as `social_exchange_psychology` - --> $DIR/reasons.rs:28:9 + --> $DIR/reasons.rs:30:9 | LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; = note: people shouldn't have to change their usual style habits to contribute to our project note: lint level defined here - --> $DIR/reasons.rs:7:5 + --> $DIR/reasons.rs:9:5 | LL | nonstandard_style, | ^^^^^^^^^^^^^^^^^ From f90de1110d93ea389342220caad19e05c4e6ad10 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 12 Oct 2018 00:21:21 -0700 Subject: [PATCH 32/33] in which lint reasons are restricted to come last in the attribute Vadim Petrochenkov suggested this in review ("an error? just to be conservative"), and it turns out to be convenient from the implementer's perspective: in the initial proposed implementation (or `HEAD~2`, as some might prefer to call it), we were doing an entire whole iteration over the meta items just to find the reason (before iterating over them to set the actual lint levels). This way, we can just peek at the end rather than adding that extra loop (or restructuring the existing code). The RFC doesn't seem to take a position on this, and there's some precedent for restricting things to be at the end of a sequence (we only allow `..` at the end of a struct pattern, even if it would be possible to let it appear anywhere in the sequence). --- src/librustc/lint/levels.rs | 73 +++++++++++++---------- src/test/ui/lint/reasons-erroneous.rs | 8 ++- src/test/ui/lint/reasons-erroneous.stderr | 24 ++++++-- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index ee878da00660e..d44facedc8b7c 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -21,6 +21,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, use session::Session; use syntax::ast; use syntax::attr; +use syntax::feature_gate; use syntax::source_map::MultiSpan; use syntax::symbol::Symbol; use util::nodemap::FxHashMap; @@ -210,7 +211,7 @@ impl<'a> LintLevelsBuilder<'a> { let meta = unwrap_or!(attr.meta(), continue); attr::mark_used(attr); - let metas = if let Some(metas) = meta.meta_item_list() { + let mut metas = if let Some(metas) = meta.meta_item_list() { metas } else { let mut err = bad_attr(meta.span); @@ -218,44 +219,43 @@ impl<'a> LintLevelsBuilder<'a> { continue }; - // Before processing the lint names, look for a reason (RFC 2383). + // Before processing the lint names, look for a reason (RFC 2383) + // at the end. let mut reason = None; - for li in metas { - if let Some(item) = li.meta_item() { - match item.node { - ast::MetaItemKind::Word => {} // actual lint names handled later - ast::MetaItemKind::NameValue(ref name_value) => { - let gate_reasons = !self.sess.features_untracked().lint_reasons; - let name_ident = item.ident.segments[0].ident; - let name = name_ident.name.as_str(); - - if name == "reason" { - if let ast::LitKind::Str(rationale, _) = name_value.node { - if gate_reasons { - feature_gate::emit_feature_err( - &self.sess.parse_sess, - "lint_reasons", - item.span, - feature_gate::GateIssue::Language, - "lint reasons are experimental" - ); - } else { - reason = Some(rationale); - } + let tail_li = &metas[metas.len()-1]; + if let Some(item) = tail_li.meta_item() { + match item.node { + ast::MetaItemKind::Word => {} // actual lint names handled later + ast::MetaItemKind::NameValue(ref name_value) => { + let gate_reasons = !self.sess.features_untracked().lint_reasons; + if item.ident == "reason" { + // found reason, reslice meta list to exclude it + metas = &metas[0..metas.len()-1]; + if let ast::LitKind::Str(rationale, _) = name_value.node { + if gate_reasons { + feature_gate::emit_feature_err( + &self.sess.parse_sess, + "lint_reasons", + item.span, + feature_gate::GateIssue::Language, + "lint reasons are experimental" + ); } else { - let mut err = bad_attr(name_value.span); - err.help("reason must be a string literal"); - err.emit(); + reason = Some(rationale); } } else { - let mut err = bad_attr(item.span); + let mut err = bad_attr(name_value.span); + err.help("reason must be a string literal"); err.emit(); } - }, - ast::MetaItemKind::List(_) => { + } else { let mut err = bad_attr(item.span); err.emit(); } + }, + ast::MetaItemKind::List(_) => { + let mut err = bad_attr(item.span); + err.emit(); } } } @@ -263,7 +263,18 @@ impl<'a> LintLevelsBuilder<'a> { for li in metas { let word = match li.word() { Some(word) => word, - None => { continue; } + None => { + let mut err = bad_attr(li.span); + if let Some(item) = li.meta_item() { + if let ast::MetaItemKind::NameValue(_) = item.node { + if item.ident == "reason" { + err.help("reason in lint attribute must come last"); + } + } + } + err.emit(); + continue; + } }; let tool_name = if let Some(lint_tool) = word.is_scoped() { if !attr::is_known_lint_tool(lint_tool) { diff --git a/src/test/ui/lint/reasons-erroneous.rs b/src/test/ui/lint/reasons-erroneous.rs index 90111a9c4e1e9..e42b329338b5a 100644 --- a/src/test/ui/lint/reasons-erroneous.rs +++ b/src/test/ui/lint/reasons-erroneous.rs @@ -12,7 +12,13 @@ //~^ ERROR malformed lint attribute #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] //~^ ERROR malformed lint attribute -#![warn(ellipsis_inclusive_range_patterns, reason)] +#![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] +//~^ ERROR malformed lint attribute +//~| HELP reason in lint attribute must come last +#![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] +//~^ ERROR malformed lint attribute +//~| HELP reason in lint attribute must come last +#![warn(missing_copy_implementations, reason)] //~^ WARN unknown lint fn main() {} diff --git a/src/test/ui/lint/reasons-erroneous.stderr b/src/test/ui/lint/reasons-erroneous.stderr index f66999e927203..6842686ecbab5 100644 --- a/src/test/ui/lint/reasons-erroneous.stderr +++ b/src/test/ui/lint/reasons-erroneous.stderr @@ -32,14 +32,30 @@ error[E0452]: malformed lint attribute LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: unknown lint: `reason` +error[E0452]: malformed lint attribute --> $DIR/reasons-erroneous.rs:15:44 | -LL | #![warn(ellipsis_inclusive_range_patterns, reason)] - | ^^^^^^ +LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: reason in lint attribute must come last + +error[E0452]: malformed lint attribute + --> $DIR/reasons-erroneous.rs:18:25 + | +LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: reason in lint attribute must come last + +warning: unknown lint: `reason` + --> $DIR/reasons-erroneous.rs:21:39 + | +LL | #![warn(missing_copy_implementations, reason)] + | ^^^^^^ | = note: #[warn(unknown_lints)] on by default -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0452`. From f66ea66acd1c5e24e16fafe28021af1b723d6824 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Mon, 15 Oct 2018 23:35:58 -0700 Subject: [PATCH 33/33] wherein the status of empty and reason-only lint attributes is clarified We avoid an ICE by checking for an empty meta-item list before we index into the meta-items, and leave commentary about where we'd like to issue unused-attributes lints in the future. Note that empty lint attributes are already accepted by the stable compiler; generalizing this to weird reason-only lint attributes seems like the conservative/consilient generalization. --- src/librustc/lint/levels.rs | 9 ++++++++- src/test/ui/lint/empty-lint-attributes.rs | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/lint/empty-lint-attributes.rs diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index d44facedc8b7c..732b32cc35d68 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -216,9 +216,14 @@ impl<'a> LintLevelsBuilder<'a> { } else { let mut err = bad_attr(meta.span); err.emit(); - continue + continue; }; + if metas.is_empty() { + // FIXME (#55112): issue unused-attributes lint for `#[level()]` + continue; + } + // Before processing the lint names, look for a reason (RFC 2383) // at the end. let mut reason = None; @@ -231,6 +236,8 @@ impl<'a> LintLevelsBuilder<'a> { if item.ident == "reason" { // found reason, reslice meta list to exclude it metas = &metas[0..metas.len()-1]; + // FIXME (#55112): issue unused-attributes lint if we thereby + // don't have any lint names (`#[level(reason = "foo")]`) if let ast::LitKind::Str(rationale, _) = name_value.node { if gate_reasons { feature_gate::emit_feature_err( diff --git a/src/test/ui/lint/empty-lint-attributes.rs b/src/test/ui/lint/empty-lint-attributes.rs new file mode 100644 index 0000000000000..1f0a9538d88b1 --- /dev/null +++ b/src/test/ui/lint/empty-lint-attributes.rs @@ -0,0 +1,17 @@ +#![feature(lint_reasons)] + +// run-pass + +// Empty (and reason-only) lint attributes are legal—although we may want to +// lint them in the future (Issue #55112). + +#![allow()] +#![warn(reason = "observationalism")] + +#[forbid()] +fn devoir() {} + +#[deny(reason = "ultion")] +fn waldgrave() {} + +fn main() {}