diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index a73fe2b8a1ab3..910427da044d4 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -453,6 +453,7 @@ impl_stable_hash_for!(enum mir::CastKind { ReifyFnPointer, ClosureFnPointer, UnsafeFnPointer, + Hide, Unsize }); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index ac54cd972cba8..30bc242524ef2 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -183,10 +183,8 @@ for ty::adjustment::Adjust<'gcx> { ty::adjustment::Adjust::UnsafeFnPointer | ty::adjustment::Adjust::ClosureFnPointer | ty::adjustment::Adjust::MutToConstPointer | + ty::adjustment::Adjust::Hide | ty::adjustment::Adjust::Unsize => {} - ty::adjustment::Adjust::Hide(ref revealed_ty) => { - revealed_ty.hash_stable(hcx, hasher); - } ty::adjustment::Adjust::Deref(ref overloaded) => { overloaded.hash_stable(hcx, hasher); } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f5513acecf9e7..a5db5fe95f0a8 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1057,7 +1057,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Substs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param)) } - /// True if errors have been reported since this infcx was + /// Returns `true` if errors have been reported since this infcx was /// created. This is sometimes used as a heuristic to skip /// reporting errors that often occur as a result of earlier /// errors, but where it's hard to be 100% sure (e.g., unresolved @@ -1251,7 +1251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { value.fold_with(&mut r) } - /// Returns true if `T` contains unresolved type variables. In the + /// Returns `true` if `T` contains unresolved type variables. In the /// process of visiting `T`, this will resolve (where possible) /// type variables in `T`, but it never constructs the final, /// resolved type, so it's more efficient than diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 722a92895a0cf..7a3f1974f2110 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -721,7 +721,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { adjustment::Adjust::UnsafeFnPointer | adjustment::Adjust::ClosureFnPointer | adjustment::Adjust::MutToConstPointer | - adjustment::Adjust::Hide(_) | + adjustment::Adjust::Hide | adjustment::Adjust::Unsize => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 20225b8ecf5cd..2df048c70a2a3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -631,7 +631,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { adjustment::Adjust::ClosureFnPointer | adjustment::Adjust::MutToConstPointer | adjustment::Adjust::Borrow(_) | - adjustment::Adjust::Hide(_) | + adjustment::Adjust::Hide | adjustment::Adjust::Unsize => { // Result is an rvalue. Ok(self.cat_rvalue_node(expr.hir_id, expr.span, target)) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c2014a5fdd23a..e6081ff5d5f9c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2128,16 +2128,16 @@ impl<'tcx> Operand<'tcx> { #[derive(Clone, RustcEncodable, RustcDecodable)] pub enum Rvalue<'tcx> { - /// x (either a move or copy, depending on type of x) + /// `x` (either a move or copy, depending on type of `x`) Use(Operand<'tcx>), - /// [x; 32] + /// `[x; 32]` Repeat(Operand<'tcx>, u64), - /// &x or &mut x + /// `&x` or `&mut x` Ref(Region<'tcx>, BorrowKind, Place<'tcx>), - /// length of a [X] or [X;n] value + /// length of a `[X]` or `[X;n]` value Len(Place<'tcx>), Cast(CastKind, Operand<'tcx>, Ty<'tcx>), @@ -2166,15 +2166,19 @@ pub enum Rvalue<'tcx> { pub enum CastKind { Misc, - /// Convert unique, zero-sized type for a fn to fn() + /// Convert a unique, zero-sized type for a fn to `fn()` ReifyFnPointer, - /// Convert non capturing closure to fn() + /// Convert a non capturing closure to `fn()` ClosureFnPointer, - /// Convert safe fn() to unsafe fn() + /// Convert a safe fn() to unsafe `fn()` UnsafeFnPointer, + // "Hide" -- convert a value to an opaque type, i.e. `impl Trait`, + // thus hiding information about its conrete type. + Hide, + /// "Unsize" -- convert a thin-or-fat pointer to a fat pointer. /// codegen must figure out the details once full monomorphization /// is known. For example, this could be used to cast from a @@ -2185,7 +2189,7 @@ pub enum CastKind { #[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum AggregateKind<'tcx> { - /// The type is of the element + /// The type is of the element. Array(Ty<'tcx>), Tuple, diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 78176dd3a09d2..98ac4035d64b7 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -13,7 +13,6 @@ use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use ty::subst::Substs; - /// Represents coercing a value to a different type of value. /// /// We transform values by following a number of `Adjust` steps in order. @@ -84,7 +83,7 @@ pub enum Adjust<'tcx> { Borrow(AutoBorrow<'tcx>), /// Hide a value with an opaque type. - Hide(Ty<'tcx>), + Hide, /// Unsize a pointer/reference value, e.g. `&[T; n]` to /// `&[T]`. Note that the source could be a thin or fat pointer. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 73d1ba4756e0c..36be45a562409 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -346,8 +346,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> { Some(ty::adjustment::Adjust::ClosureFnPointer), ty::adjustment::Adjust::MutToConstPointer => Some(ty::adjustment::Adjust::MutToConstPointer), - ty::adjustment::Adjust::Hide(ref revealed_ty) => - tcx.lift(revealed_ty).map(ty::adjustment::Adjust::Hide), + ty::adjustment::Adjust::Hide => + Some(ty::adjustment::Adjust::Hide), ty::adjustment::Adjust::Unsize => Some(ty::adjustment::Adjust::Unsize), ty::adjustment::Adjust::Deref(ref overloaded) => { @@ -883,7 +883,7 @@ EnumTypeFoldableImpl! { (ty::adjustment::Adjust::UnsafeFnPointer), (ty::adjustment::Adjust::ClosureFnPointer), (ty::adjustment::Adjust::MutToConstPointer), - (ty::adjustment::Adjust::Hide)(a), + (ty::adjustment::Adjust::Hide), (ty::adjustment::Adjust::Unsize), (ty::adjustment::Adjust::Deref)(a), (ty::adjustment::Adjust::Borrow)(a), diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs index fa22bdff94ddd..4abf511712e13 100644 --- a/src/librustc_codegen_llvm/mir/rvalue.rs +++ b/src/librustc_codegen_llvm/mir/rvalue.rs @@ -240,7 +240,11 @@ impl FunctionCx<'a, 'll, 'tcx> { } } mir::CastKind::UnsafeFnPointer => { - // this is a no-op at the LLVM level + // This is a no-op at the LLVM level. + operand.val + } + mir::CastKind::Hide => { + // This is a no-op at the LLVM level. operand.val } mir::CastKind::Unsize => { 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 734ddbc3ab9a7..d1ec07b4ccbc0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -973,6 +973,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { + // FIXME(alexreg): see issue #54600. if let Err(terr) = self.sub_types(sub, sup, locations, category) { if let TyKind::Opaque(..) = sup.sty { // When you have `let x: impl Foo = ...` in a closure, @@ -1059,17 +1060,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { fn eq_opaque_type_and_type( &mut self, - revealed_ty: Ty<'tcx>, - anon_ty: Ty<'tcx>, - anon_owner_def_id: DefId, + concrete_ty: Ty<'tcx>, + opaque_ty: Ty<'tcx>, + parent_def_id: DefId, locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { debug!( "eq_opaque_type_and_type( \ - revealed_ty={:?}, \ - anon_ty={:?})", - revealed_ty, anon_ty + concrete_ty={:?}, \ + opaque_ty={:?})", + concrete_ty, opaque_ty ); let infcx = self.infcx; let tcx = infcx.tcx; @@ -1085,21 +1086,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let dummy_body_id = ObligationCause::dummy().body_id; let (output_ty, opaque_type_map) = obligations.add(infcx.instantiate_opaque_types( - anon_owner_def_id, + parent_def_id, dummy_body_id, param_env, - &anon_ty, + &opaque_ty, )); debug!( "eq_opaque_type_and_type: \ instantiated output_ty={:?} \ opaque_type_map={:#?} \ - revealed_ty={:?}", - output_ty, opaque_type_map, revealed_ty + concrete_ty={:?}", + output_ty, opaque_type_map, concrete_ty ); obligations.add(infcx .at(&ObligationCause::dummy(), param_env) - .eq(output_ty, revealed_ty)?); + .eq(output_ty, concrete_ty)?); for (&opaque_def_id, opaque_decl) in &opaque_type_map { let opaque_defn_ty = tcx.type_of(opaque_def_id); @@ -1524,7 +1525,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } None => { - // FIXME(canndrew): This is_never should probably be an is_uninhabited + // FIXME(canndrew): this `is_never` should probably be an `is_uninhabited`. if !sig.output().is_never() { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } @@ -1910,6 +1911,25 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } + CastKind::Hide => { + let predicates = match ty.sty { + ty::Opaque(def_id, substs) => { + let bounds = tcx.predicates_of(def_id); + let result = bounds.instantiate(tcx, substs); + // TODO: do I need to normalize associated types here somehow. + // as is done in coercion.rs? + result + } + _ => bug!(), + }; + + self.prove_predicates( + predicates.predicates, + location.to_locations(), + ConstraintCategory::Cast, + ); + } + CastKind::Unsize => { let &ty = ty; let trait_ref = ty::TraitRef { @@ -1932,7 +1952,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.add_reborrow_constraint(location, region, borrowed_place); } - // FIXME: These other cases have to be implemented in future PRs + // FIXME: these other cases have to be implemented in future PRs. Rvalue::Use(..) | Rvalue::Len(..) | Rvalue::BinaryOp(..) @@ -2164,7 +2184,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } // For closures, we have some **extra requirements** we - // // have to check. In particular, in their upvars and // signatures, closures often reference various regions // from the surrounding function -- we call those the diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 77746e5538d65..e7938b00f5fe9 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -189,6 +189,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | ExprKind::ReifyFnPointer { .. } | ExprKind::ClosureFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } + | ExprKind::Hide { .. } | ExprKind::Unsize { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } @@ -205,7 +206,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | ExprKind::InlineAsm { .. } | ExprKind::Yield { .. } | ExprKind::Call { .. } => { - // these are not places, so we need to make a temporary. + // These are not places, so we need to make a temporary. debug_assert!(match Category::of(&expr.kind) { Some(Category::Place) => false, _ => true, diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 8fee74390cc6b..749203765abb6 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -174,6 +174,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let source = unpack!(block = this.as_operand(block, scope, source)); block.and(Rvalue::Cast(CastKind::ClosureFnPointer, source, expr.ty)) } + ExprKind::Hide { source } => { + let source = this.hir.mirror(source); + + let source = unpack!(block = this.as_operand(block, scope, source)); + block.and(Rvalue::Cast(CastKind::Hide, source, expr.ty)) + } ExprKind::Unsize { source } => { let source = unpack!(block = this.as_operand(block, scope, source)); block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty)) diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 05a9079cdb1ef..d85c268bf8abc 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -72,6 +72,7 @@ impl Category { | ExprKind::ReifyFnPointer { .. } | ExprKind::ClosureFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } + | ExprKind::Hide { .. } | ExprKind::Unsize { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index d2913872fca45..4ff69aa194e9c 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -399,6 +399,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { | ExprKind::ReifyFnPointer { .. } | ExprKind::ClosureFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } + | ExprKind::Hide { .. } | ExprKind::Unsize { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index cd71a768d8308..f2c987ac60ff0 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -9,19 +9,19 @@ // except according to those terms. use hair::*; -use rustc_data_structures::indexed_vec::Idx; use hair::cx::Cx; use hair::cx::block; use hair::cx::to_ref::ToRef; use hair::util::UserAnnotatedTyHelpers; use rustc::hir::def::{Def, CtorKind}; +use rustc::mir::{BorrowKind}; use rustc::mir::interpret::{GlobalId, ErrorHandled}; use rustc::ty::{self, AdtKind, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; use rustc::hir::def_id::LocalDefId; -use rustc::mir::{BorrowKind}; +use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { @@ -150,9 +150,8 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } Adjust::Borrow(AutoBorrow::RawPtr(m)) => { - // Convert this to a suitable `&foo` and - // then an unsafe coercion. Limit the region to be just this - // expression. + // Convert this to a suitable `&foo` and then an unsafe coercion. + // Limit the region to be just this expression. let region = ty::ReScope(region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node @@ -162,8 +161,8 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, temp_lifetime, ty: cx.tcx.mk_ref(region, ty::TypeAndMut { - ty: expr.ty, - mutbl: m, + ty: expr.ty, + mutbl: m, }), span, kind: ExprKind::Borrow { @@ -181,45 +180,43 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // To ensure that both implicit and explicit coercions are // handled the same way, we insert an extra layer of indirection here. - // For explicit casts (e.g. 'foo as *const T'), the source of the 'Use' - // will be an ExprKind::Hair with the appropriate cast expression. Here, - // we make our Use source the generated Cast from the original coercion. + // For explicit casts (e.g. `foo as *const T`), the source of the `Use` + // will be an `ExprKind::Hair` with the appropriate cast expression. Here, + // we make our Use source the generated `Cast` from the original coercion. // - // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by - // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary. - // Ordinary, this is identical to using the cast directly as an rvalue. However, if the - // source of the cast was previously borrowed as mutable, storing the cast in a - // temporary gives the source a chance to expire before the cast is used. For - // structs with a self-referential *mut ptr, this allows assignment to work as + // In both cases, this outer `Use` ensures that the inner 'Cast' is handled by + // `as_operand`, not by `as_rvalue` - causing the cast result to be stored in a + // temporary. Ordinarily, this is identical to using the cast directly as an rvalue. + // However, if the source of the cast was previously borrowed as mutable, storing the + // cast in a temporary gives the source a chance to expire before the cast is used. + // For structs with a self-referential `*mut ptr`, this allows assignment to work as // expected. // - // For example, consider the type 'struct Foo { field: *mut Foo }', - // The method 'fn bar(&mut self) { self.field = self }' - // triggers a coercion from '&mut self' to '*mut self'. In order + // For example, consider the type `struct Foo { field: *mut Foo }`, + // The method `fn bar(&mut self) { self.field = self }` + // triggers a coercion from `&mut self` to `*mut self`. In order // for the assignment to be valid, the implicit borrow - // of 'self' involved in the coercion needs to end before the local - // containing the '*mut T' is assigned to 'self.field' - otherwise, - // we end up trying to assign to 'self.field' while we have another mutable borrow + // of `self` involved in the coercion needs to end before the local + // containing the `*mut T` is assigned to `self.field` -- otherwise, + // we end up trying to assign to `self.field` while we have another mutable borrow // active. // // We only need to worry about this kind of thing for coercions from refs to ptrs, // since they get rid of a borrow implicitly. ExprKind::Use { source: cast_expr.to_ref() } } - Adjust::Hide(revealed_ty) => { - // See the above comment for Adjust::Deref. + Adjust::Hide => { + // See the above comment for `Adjust::Deref`. if let ExprKind::Block { body } = expr.kind { if let Some(ref last_expr) = body.expr { span = last_expr.span; expr.span = span; } } - expr.ty = revealed_ty; - debug!("hide: {:?} {:?}", expr, revealed_ty); - ExprKind::Cast { source: expr.to_ref() } + ExprKind::Hide { source: expr.to_ref() } } Adjust::Unsize => { - // See the above comment for Adjust::Deref. + // See the above comment for `Adjust::Deref`. if let ExprKind::Block { body } = expr.kind { if let Some(ref last_expr) = body.expr { span = last_expr.span; @@ -664,25 +661,25 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Check to see if this cast is a "coercion cast", where the cast is actually done // using a coercion (or is a no-op). - let cast = if let Some(&TyCastKind::CoercionCast) = - cx.tables() + let cast = if let Some(&TyCastKind::CoercionCast) = cx + .tables() .cast_kinds() .get(source.hir_id) { // Convert the lexpr to a vexpr. ExprKind::Use { source: source.to_ref() } } else { - // check whether this is casting an enum variant discriminant + // Check whether this is casting an enum variant discriminant // to prevent cycles, we refer to the discriminant initializer // which is always an integer and thus doesn't need to know the - // enum's layout (or its tag type) to compute it during const eval + // enum's layout (or its tag type) to compute it during const eval. // Example: // enum Foo { // A, // B = A as isize + 4, // } // The correct solution would be to add symbolic computations to miri, - // so we wouldn't have to compute and store the actual value + // so we wouldn't have to compute and store the actual value. let var = if let hir::ExprKind::Path(ref qpath) = source.node { let def = cx.tables().qpath_def(qpath, source.hir_id); cx @@ -751,8 +748,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; if let Some(user_ty) = user_ty { - // NOTE: Creating a new Expr and wrapping a Cast inside of it may be - // inefficient, revisit this when performance becomes an issue. + // NOTE: Creating a new `Expr` and wrapping a `Cast` inside of it may be + // inefficient; revisit this when performance becomes an issue. let cast_expr = Expr { temp_lifetime, ty: expr_ty, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3a56d261111ee..2596c6eb635f1 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -10,9 +10,8 @@ //! This module contains the code to convert from the wacky tcx data //! structures into the hair. The `builder` is generally ignorant of -//! the tcx etc, and instead goes through the `Cx` for most of its -//! work. -//! +//! the tcx and whatnot, and instead goes through the `Cx` for most of +//! its work. use hair::*; use hair::util::UserAnnotatedTyHelpers; @@ -77,7 +76,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { // the settings for the crate they are codegened in. let mut check_overflow = attr::contains_name(attrs, "rustc_inherit_overflow_checks"); - // Respect -C overflow-checks. + // Respect `-C overflow-checks` compiler flag. check_overflow |= tcx.sess.overflow_checks(); // Constants always need overflow checks. @@ -130,7 +129,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty::Const::from_bool(self.tcx, false) } - // FIXME: Combine with rustc_mir::hair::pattern::lit_to_const + // FIXME: Combine with `rustc_mir::hair::pattern::lit_to_const`. pub fn const_eval_literal( &mut self, lit: &'tcx ast::LitKind, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index b2ed3f03abc4e..b981cde1a1a60 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -193,9 +193,9 @@ pub enum ExprKind<'tcx> { UnsafeFnPointer { source: ExprRef<'tcx>, }, - // Hide { - // source: ExprRef<'tcx>, - // }, + Hide { + source: ExprRef<'tcx>, + }, Unsize { source: ExprRef<'tcx>, }, diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 06748d60e4583..0305394e953fb 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -39,6 +39,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ) -> EvalResult<'tcx> { use rustc::mir::CastKind::*; match kind { + Hide => { + unimplemented!(); + } + Unsize => { self.unsize_into(src, dest)?; } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ca9c4eb9b8bb9..457b47f7b244a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -642,6 +642,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { Rvalue::Cast(CastKind::ReifyFnPointer, ..) | Rvalue::Cast(CastKind::UnsafeFnPointer, ..) | Rvalue::Cast(CastKind::ClosureFnPointer, ..) | + Rvalue::Cast(CastKind::Hide, ..) | Rvalue::Cast(CastKind::Unsize, ..) | Rvalue::Discriminant(..) | Rvalue::Len(_) => {} @@ -756,11 +757,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => { if let Mode::Fn = self.mode { - // in normal functions, mark such casts as not promotable + // In normal functions, mark such casts as not promotable. self.add(Qualif::NOT_CONST); } else if !self.tcx.sess.features_untracked().const_raw_ptr_to_usize_cast { - // in const fn and constants require the feature gate - // FIXME: make it unsafe inside const fn and constants + // In const functions and constants require the feature gate. + // FIXME: make it unsafe inside const fn and constants. emit_feature_err( &self.tcx.sess.parse_sess, "const_raw_ptr_to_usize_cast", self.span, GateIssue::Language, @@ -783,11 +784,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { op == BinOp::Offset); if let Mode::Fn = self.mode { - // raw pointer operations are not allowed inside promoteds + // Raw pointer operations are not allowed inside promoteds. self.add(Qualif::NOT_CONST); } else if !self.tcx.sess.features_untracked().const_compare_raw_pointers { - // require the feature gate inside constants and const fn - // FIXME: make it unsafe to use these operations + // Require the feature gate inside constants and const fn. + // FIXME: make it unsafe to use these operations. emit_feature_err( &self.tcx.sess.parse_sess, "const_compare_raw_pointers", @@ -872,16 +873,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" - // no need to check feature gates, intrinsics are only callable from the - // libstd or with forever unstable feature gates + // No need to check feature gates, intrinsics are only callable from the + // libstd or with forever unstable feature gates. => is_const_fn = true, - // special intrinsic that can be called diretly without an intrinsic - // feature gate needs a language feature gate + // Special intrinsic that can be called diretly without an intrinsic + // feature gate needs a language feature gate. "transmute" => { - // never promote transmute calls + // Never promote transmute calls. if self.mode != Mode::Fn { is_const_fn = true; - // const eval transmute calls only with the feature gate + // Const-eval transmute calls only with the feature gate. if !self.tcx.sess.features_untracked().const_transmute { emit_feature_err( &self.tcx.sess.parse_sess, "const_transmute", @@ -900,10 +901,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } _ => { - // in normal functions we only care about promotion + // In normal functions we only care about promotion. if self.mode == Mode::Fn { - // never promote const fn calls of - // functions without #[rustc_promotable] + // Never promote const fn calls of + // functions without `#[rustc_promotable]`. if self.tcx.is_promotable_const_fn(def_id) { is_const_fn = true; is_promotable_const_fn = true; @@ -911,19 +912,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { is_const_fn = true; } } else { - // stable const fn or unstable const fns with their feature gate - // active + // Stable const fn or unstable const fns with their feature gate + // active. if self.tcx.is_const_fn(def_id) { is_const_fn = true; } else if self.is_const_panic_fn(def_id) { - // check the const_panic feature gate + // Check the `const_panic` feature gate. // FIXME: cannot allow this inside `allow_internal_unstable` because // that would make `panic!` insta stable in constants, since the - // macro is marked with the attr + // macro is marked with the attr. if self.tcx.sess.features_untracked().const_panic { is_const_fn = true; } else { - // don't allow panics in constants without the feature gate + // Don't allow panics in constants without the feature gate. emit_feature_err( &self.tcx.sess.parse_sess, "const_panic", @@ -933,11 +934,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { ); } } else if let Some(feature) = self.tcx.is_unstable_const_fn(def_id) { - // check `#[unstable]` const fns or `#[rustc_const_unstable]` + // Check `#[unstable]` const fns or `#[rustc_const_unstable]` // functions without the feature gate active in this crate to report - // a better error message than the one below + // a better error message than the one below. if self.span.allows_unstable() { - // `allow_internal_unstable` can make such calls stable + // `allow_internal_unstable` can make such calls stable. is_const_fn = true; } else { let mut err = self.tcx.sess.struct_span_err(self.span, @@ -950,7 +951,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { err.emit(); } } else { - // FIXME(#24111) Remove this check when const fn stabilizes + // FIXME(#24111): remove this check when const fn stabilizes. let (msg, note) = if let UnstableFeatures::Disallow = self.tcx.sess.opts.unstable_features { (format!("calls in {}s are limited to \ @@ -1032,7 +1033,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { }); } - // non-const fn calls. + // non-const fn calls if !is_const_fn { self.qualif = Qualif::NOT_CONST; if self.mode != Mode::Fn { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 1e19348595057..99c94c84b035f 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -169,6 +169,10 @@ fn check_rvalue( span, "function pointer casts are not allowed in const fn".into(), )), + Rvalue::Cast(CastKind::Hide, _, _) => Err(( + span, + "hiding casts are not allowed in const fn".into(), + )), Rvalue::Cast(CastKind::Unsize, _, _) => Err(( span, "unsizing casts are not allowed in const fn".into(), diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index d151b92269781..86a3abc89175c 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -615,7 +615,7 @@ fn check_adjustments<'a, 'tcx>( Adjust::ClosureFnPointer | Adjust::MutToConstPointer | Adjust::Borrow(_) | - Adjust::Hide(_) | + Adjust::Hide | Adjust::Unsize => {} Adjust::Deref(_) => { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 9c6ea729198ea..f98a5decb547a 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -68,7 +68,7 @@ use rustc::infer::{Coercion, InferResult, InferOk}; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; -use rustc::ty::{self, DefIdTree, TypeAndMut, Ty, ClosureSubsts}; +use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; @@ -516,7 +516,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // Handle reborrows before checking target is subtype of source. let reborrow = self.reborrow(source, target)?; - let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target); // Set up either a subtyping or a LUB relationship between // the opaque type and the expected type. @@ -526,7 +525,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let coerce_target = self.next_ty_var(origin); let mut coercion = self.unify_and(coerce_target, target, |target| { let hide = Adjustment { - kind: Adjust::Hide(coerce_source), + kind: Adjust::Hide, target }; match reborrow { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 574e402fa892a..7602cf399c54e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -180,7 +180,7 @@ impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> { } } -/// closures defined within the function. For example: +/// Closures defined within the function. For example: /// /// fn foo() { /// bar(move|| { ... }) @@ -230,6 +230,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> { type Target = InferCtxt<'a, 'gcx, 'tcx>; + fn deref(&self) -> &Self::Target { &self.infcx } @@ -574,6 +575,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> { type Target = Inherited<'a, 'gcx, 'tcx>; + fn deref(&self) -> &Self::Target { &self.inh } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index e5a1ff6bc6b21..672a1328ac91b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -8,9 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Type resolution: the phase that finds all the types in the AST with -// unresolved type variables and replaces "ty_var" types with their -// substitutions. +/* + +# Writeback + +This phase of type resolution finds all the types in the AST with +unresolved type variables and replaces "ty_var" types with their +substitutions. + +*/ use check::FnCtxt; use rustc::hir; @@ -526,7 +532,6 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - debug!("visit_opaque_types: bar1: {:?} {:?} {:?}", span, def_id, definition_ty); let old = self.tables .concrete_existential_types .insert(def_id, definition_ty); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0335f45b0a526..f5f0ae7af055c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1184,7 +1184,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { impl_trait_fn: None, .. }) => find_existential_constraints(tcx, def_id), - // existential types desugared from impl Trait + // existential types desugared from `impl Trait` ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(owner), .. @@ -1194,17 +1194,8 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { .get(&def_id) .cloned() .unwrap_or_else(|| { - // This can occur if some error in the - // owner fn prevented us from populating - // the `concrete_existential_types` table. - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no existential type for {:?} in its tables", - owner, def_id, - ), - ); - tcx.types.err + let substs = Substs::identity_for_item(tcx, def_id); + tcx.mk_opaque(def_id, substs) }) } ItemKind::Trait(..) @@ -1708,7 +1699,7 @@ fn explicit_predicates_of<'a, 'tcx>( let substs = Substs::identity_for_item(tcx, def_id); let opaque_ty = tcx.mk_opaque(def_id, substs); - // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. + // Collect the bounds, i.e. the `A + B + 'c` in `impl A + B + 'c`. let bounds = compute_bounds( &icx, opaque_ty,