diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 7d25ecedb4e04..ac54cd972cba8 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -184,6 +184,9 @@ for ty::adjustment::Adjust<'gcx> { ty::adjustment::Adjust::ClosureFnPointer | ty::adjustment::Adjust::MutToConstPointer | 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/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7e9b26bbf729c..722a92895a0cf 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -721,6 +721,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { adjustment::Adjust::UnsafeFnPointer | adjustment::Adjust::ClosureFnPointer | adjustment::Adjust::MutToConstPointer | + 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 9d3f37bc36a9d..20225b8ecf5cd 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -631,6 +631,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { adjustment::Adjust::ClosureFnPointer | adjustment::Adjust::MutToConstPointer | adjustment::Adjust::Borrow(_) | + 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/traits/mod.rs b/src/librustc/traits/mod.rs index b7512790bfb69..8b3e364a4d4a2 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -94,7 +94,7 @@ pub enum TraitQueryMode { Canonical, } -/// An `Obligation` represents some trait reference (e.g. `int:Eq`) for +/// An `Obligation` represents some trait reference (e.g. `int: Eq`) for /// which the vtable must be found. The process of finding a vtable is /// called "resolving" the `Obligation`. This process consists of /// either identifying an `impl` (e.g., `impl Eq for int`) that @@ -1015,7 +1015,7 @@ fn vtable_methods<'a, 'tcx>( ) } -impl<'tcx,O> Obligation<'tcx,O> { +impl<'tcx, O> Obligation<'tcx, O> { pub fn new(cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, predicate: O) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 74f8d67ce0484..27ed7829349b2 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -393,7 +393,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, (impl_trait_ref, impl_obligations) } -/// See `super::obligations_for_generics` +/// See `super::predicates_for_generics`. pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index 3263da8fda365..78176dd3a09d2 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -83,6 +83,9 @@ pub enum Adjust<'tcx> { /// Take the address and produce either a `&` or `*` pointer. Borrow(AutoBorrow<'tcx>), + /// Hide a value with an opaque type. + Hide(Ty<'tcx>), + /// Unsize a pointer/reference value, e.g. `&[T; n]` to /// `&[T]`. Note that the source could be a thin or fat pointer. /// This will do things like convert thin pointers to fat diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c7c197d11c03b..36334dd6ce544 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -993,6 +993,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { self.instantiate_into(tcx, &mut instantiated, substs); instantiated } + pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) -> InstantiatedPredicates<'tcx> { InstantiatedPredicates { @@ -1028,8 +1029,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, poly_trait_ref: &ty::PolyTraitRef<'tcx>) - -> InstantiatedPredicates<'tcx> - { + -> InstantiatedPredicates<'tcx> { assert_eq!(self.parent, None); InstantiatedPredicates { predicates: self.predicates.iter().map(|(pred, _)| { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 59a66513eef05..73d1ba4756e0c 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -346,6 +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::Unsize => Some(ty::adjustment::Adjust::Unsize), ty::adjustment::Adjust::Deref(ref overloaded) => { @@ -881,6 +883,7 @@ EnumTypeFoldableImpl! { (ty::adjustment::Adjust::UnsafeFnPointer), (ty::adjustment::Adjust::ClosureFnPointer), (ty::adjustment::Adjust::MutToConstPointer), + (ty::adjustment::Adjust::Hide)(a), (ty::adjustment::Adjust::Unsize), (ty::adjustment::Adjust::Deref)(a), (ty::adjustment::Adjust::Borrow)(a), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 28b58d62175bc..2f53ee8781ae4 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -190,8 +190,8 @@ pub enum TyKind<'tcx> { /// Opaque (`impl Trait`) type found in a return type. /// The `DefId` comes either from - /// * the `impl Trait` ast::Ty node, - /// * or the `existential type` declaration + /// * the `impl Trait` `ast::Ty` node, + /// * the `existential type` declaration. /// The substitutions are for the generics of the function in question. /// After typeck, the concrete type can be found in the `types` map. Opaque(DefId, &'tcx Substs<'tcx>), @@ -582,7 +582,7 @@ impl<'tcx> List> { #[inline] pub fn projection_bounds<'a>(&'a self) -> - impl Iterator> + 'a { + impl Iterator> + 'a { self.iter().filter_map(|predicate| { match *predicate { ExistentialPredicate::Projection(p) => Some(p), @@ -592,7 +592,7 @@ impl<'tcx> List> { } #[inline] - pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { self.iter().filter_map(|predicate| { match *predicate { ExistentialPredicate::AutoTrait(d) => Some(d), @@ -619,7 +619,7 @@ impl<'tcx> Binder<&'tcx List>> { } pub fn iter<'a>(&'a self) - -> impl DoubleEndedIterator>> + 'tcx { + -> impl DoubleEndedIterator>> + 'tcx { self.skip_binder().iter().cloned().map(Binder::bind) } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 48fcdd42ff5e0..cd71a768d8308 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -206,8 +206,20 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // 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. + 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() } + } 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; diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 8a24851de8149..b2ed3f03abc4e 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -193,6 +193,9 @@ pub enum ExprKind<'tcx> { UnsafeFnPointer { source: ExprRef<'tcx>, }, + // Hide { + // source: ExprRef<'tcx>, + // }, Unsize { source: ExprRef<'tcx>, }, diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index ca58239df8eac..d151b92269781 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -615,6 +615,7 @@ fn check_adjustments<'a, 'tcx>( Adjust::ClosureFnPointer | Adjust::MutToConstPointer | Adjust::Borrow(_) | + Adjust::Hide(_) | Adjust::Unsize => {} Adjust::Deref(_) => { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 40f2072079a5a..569119bdd9c15 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -234,7 +234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .pat_binding_modes_mut() .insert(pat.hir_id, bm); debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); - let local_ty = self.local_ty(pat.span, pat.id).decl_ty; + let local_ty = self.local_ty(pat.span, pat.id); match bm { ty::BindByReference(mutbl) => { // if the binding is like @@ -261,7 +261,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // if there are multiple arms, make sure they all agree on // what the type of the binding `x` ought to be if var_id != pat.id { - let vt = self.local_ty(pat.span, var_id).decl_ty; + let vt = self.local_ty(pat.span, var_id); self.demand_eqtype(pat.span, vt, local_ty); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 3bdd038bff19c..b6d1d1e3df487 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -82,17 +82,18 @@ struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, cause: ObligationCause<'tcx>, use_lub: bool, - /// Determines whether or not allow_two_phase_borrow is set on any + /// Determines whether or not `allow_two_phase_borrow` is set on any /// autoref adjustments we create while coercing. We don't want to /// allow deref coercions to create two-phase borrows, at least initially, /// but we do need two-phase borrows for function argument reborrows. - /// See #47489 and #48598 - /// See docs on the "AllowTwoPhase" type for a more detailed discussion + /// See #47489 and #48598. + /// See docs on the `AllowTwoPhase` type for a more detailed discussion. allow_two_phase: AllowTwoPhase, } impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> { type Target = FnCtxt<'a, 'gcx, 'tcx>; + fn deref(&self) -> &Self::Target { &self.fcx } @@ -161,6 +162,52 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { }) } + fn reborrow(&self, source: Ty<'tcx>, target: Ty<'tcx>) + -> Result, Adjustment<'tcx>)>, TypeError<'tcx>> { + Ok(match (&source.sty, &target.sty) { + (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => { + coerce_mutbls(mutbl_a, mutbl_b)?; + + let coercion = Coercion(self.cause.span); + let r_borrow = self.next_region_var(coercion); + let mutbl = match mutbl_b { + hir::MutImmutable => AutoBorrowMutability::Immutable, + hir::MutMutable => AutoBorrowMutability::Mutable { + // We don't allow two-phase borrows here, at least for initial + // implementation. If it happens that this coercion is a function argument, + // the reborrow in coerce_borrowed_ptr will pick it up. + allow_two_phase_borrow: AllowTwoPhase::No, + } + }; + Some((Adjustment { + kind: Adjust::Deref(None), + target: ty_a + }, Adjustment { + kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)), + target: self.tcx.mk_ref(r_borrow, ty::TypeAndMut { + mutbl: mutbl_b, + ty: ty_a + }) + })) + } + (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(ty::TypeAndMut { mutbl: mutbl_b, .. })) => { + coerce_mutbls(mutbl_a, mutbl_b)?; + + Some((Adjustment { + kind: Adjust::Deref(None), + target: ty_a + }, Adjustment { + kind: Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), + target: self.tcx.mk_ptr(ty::TypeAndMut { + mutbl: mutbl_b, + ty: ty_a + }) + })) + } + _ => None, + }) + } + fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { let a = self.shallow_resolve(a); debug!("Coerce.tys({:?} => {:?})", a, b); @@ -190,9 +237,20 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { }; } - // Consider coercing the subtype to a DST + // Consider coercing to an opaque type. // - // NOTE: this is wrapped in a `commit_if_ok` because it creates + // Note: this is wrapped in a `commit_if_ok` because it creates + // a "spurious" type variable, and we don't want to have that + // type variable in memory if the coercion fails. + let hide = self.commit_if_ok(|_| self.coerce_hidden(a, b)); + if hide.is_ok() { + debug!("coerce: hide successful"); + return self.coerce_hidden(a, b); + } + + // Consider coercing the subtype to a DST. + // + // Note: this is wrapped in a `commit_if_ok` because it creates // a "spurious" type variable, and we don't want to have that // type variable in memory if the coercion fails. let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b)); @@ -210,12 +268,10 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { ty::RawPtr(mt_b) => { return self.coerce_unsafe_ptr(a, b, mt_b.mutbl); } - ty::Ref(r_b, ty, mutbl) => { let mt_b = ty::TypeAndMut { ty, mutbl }; return self.coerce_borrowed_pointer(a, b, r_b, mt_b); } - _ => {} } @@ -447,6 +503,52 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { success(adjustments, ty, obligations) } + // T -> impl Bounds, where T satisfies Bounds + fn coerce_hidden(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> { + debug!("coerce_hidden(source={:?}, target={:?})", source, target); + + let target_predicates = if let ty::Opaque(def_id, substs) = target.sty { + self.instantiate_bounds(self.cause.span, def_id, substs) + } else { + debug!("coerce_hidden: target is not opaque type"); + return Err(TypeError::Mismatch); + }; + + // 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. + // We only have the latter, so we use an inference variable + // for the former and let type inference do the rest. + let origin = TypeVariableOrigin::MiscVariable(self.cause.span); + 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), + target + }; + match reborrow { + None => vec![hide], + Some((ref deref, ref autoref)) => { + vec![deref.clone(), autoref.clone(), hide] + } + } + })?; + + // Instantiate opaque type in tables. + self.fcx.instantiate_opaque_types_from_return_value(self., &coerce_source); + + // Create the obligations for `Source` satisfying the target predicates. + let cause = ObligationCause::misc(self.cause.span, self.fcx.body_id); + let obligations = traits::predicates_for_generics(cause, + self.fcx.param_env, + &target_predicates); + coercion.obligations.extend(obligations); + + Ok(coercion) + } // &[T; n] or &mut [T; n] -> &[T] // or &mut [T; n] -> &mut [T] @@ -459,7 +561,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits { (u, cu) } else { - debug!("Missing Unsize or CoerceUnsized traits"); + debug!("coerce_unsized: missing Unsize or CoerceUnsized traits"); return Err(TypeError::Mismatch); }; @@ -469,51 +571,10 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { // that, at which point we will need extra checks on the target here. // Handle reborrows before selecting `Source: CoerceUnsized`. - let reborrow = match (&source.sty, &target.sty) { - (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => { - coerce_mutbls(mutbl_a, mutbl_b)?; - - let coercion = Coercion(self.cause.span); - let r_borrow = self.next_region_var(coercion); - let mutbl = match mutbl_b { - hir::MutImmutable => AutoBorrowMutability::Immutable, - hir::MutMutable => AutoBorrowMutability::Mutable { - // We don't allow two-phase borrows here, at least for initial - // implementation. If it happens that this coercion is a function argument, - // the reborrow in coerce_borrowed_ptr will pick it up. - allow_two_phase_borrow: AllowTwoPhase::No, - } - }; - Some((Adjustment { - kind: Adjust::Deref(None), - target: ty_a - }, Adjustment { - kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)), - target: self.tcx.mk_ref(r_borrow, ty::TypeAndMut { - mutbl: mutbl_b, - ty: ty_a - }) - })) - } - (&ty::Ref(_, ty_a, mt_a), &ty::RawPtr(ty::TypeAndMut { mutbl: mt_b, .. })) => { - coerce_mutbls(mt_a, mt_b)?; - - Some((Adjustment { - kind: Adjust::Deref(None), - target: ty_a - }, Adjustment { - kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)), - target: self.tcx.mk_ptr(ty::TypeAndMut { - mutbl: mt_b, - ty: ty_a - }) - })) - } - _ => None, - }; + let reborrow = self.reborrow(source, target)?; let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target); - // Setup either a subtyping or a LUB relationship between + // Set up either a subtyping or a LUB relationship between // the `CoerceUnsized` target type and the expected type. // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. @@ -535,7 +596,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let mut selcx = traits::SelectionContext::new(self); // Create an obligation for `Source: CoerceUnsized`. - let cause = ObligationCause::misc(self.cause.span, self.body_id); + let cause = ObligationCause::misc(self.cause.span, self.fcx.body_id); // Use a FIFO queue for this custom fulfillment procedure. // @@ -776,7 +837,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(target) } - /// Same as `try_coerce()`, but without side-effects. + /// Same as `try_coerce`, but without side-effects. pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool { let source = self.resolve_type_vars_with_obligations(expr_ty); debug!("coercion::can({:?} -> {:?})", source, target); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0a196834cb494..21eca3496ca01 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -89,11 +89,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } - // Checks that the type of `expr` can be coerced to `expected`. - // - // NB: This code relies on `self.diverges` to be accurate. In - // particular, assignments to `!` will be permitted if the - // diverges flag is currently "always". + /// Checks that the type of `expr` can be coerced to `expected`. + /// + /// N.B., this code relies on `self.diverges` to be accurate. In + /// particular, assignments to `!` will be permitted if the + /// diverges flag is currently "always". pub fn demand_coerce_diag(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, @@ -111,7 +111,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); - // If the expected type is an enum (Issue #55250) with any variants whose + // If the expected type is an enum (issue #55250) with any variants whose // sole field is of the found type, suggest such variants. (Issue #42764) if let ty::Adt(expected_adt, substs) = expected.sty { if expected_adt.is_enum() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7dfdb926c60ef..97931b38446b2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -155,13 +155,6 @@ mod generator_interior; mod intrinsic; mod op; -/// The type of a local binding, including the revealed type for anon types. -#[derive(Copy, Clone)] -pub struct LocalTy<'tcx> { - decl_ty: Ty<'tcx>, - revealed_ty: Ty<'tcx> -} - /// A wrapper for InferCtxt's `in_progress_tables` field. #[derive(Copy, Clone)] struct MaybeInProgressTables<'a, 'tcx: 'a> { @@ -202,7 +195,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tables: MaybeInProgressTables<'a, 'tcx>, - locals: RefCell>>, + locals: RefCell>>, fulfillment_cx: RefCell>>, @@ -494,8 +487,8 @@ impl Diverges { pub struct BreakableCtxt<'gcx: 'tcx, 'tcx> { may_break: bool, - // this is `null` for loops where break with a value is illegal, - // such as `while`, `for`, and `while let` + // This is `null` for loops where break with a value is illegal, + // such as `while`, `for`, and `while let`. coerce: Option>, } @@ -871,19 +864,10 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); - let revealed_ty = if tcx.features().impl_trait_in_bindings { - fcx.instantiate_opaque_types_from_value( - id, - &expected_type - ) - } else { - expected_type - }; - // Gather locals in statics (because of block expressions). - GatherLocalsVisitor { fcx: &fcx, parent_id: id, }.visit_body(body); + GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); - fcx.check_expr_coercable_to_type(&body.value, revealed_ty); + fcx.check_expr_coercable_to_type(&body.value, expected_type); fcx }; @@ -932,25 +916,21 @@ fn check_abi<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, abi: Abi) { struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - parent_id: ast::NodeId, } impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> { - fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option>) -> Ty<'tcx> { + fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option>) -> Ty<'tcx> { match ty_opt { None => { - // infer the variable's type + // Infer the variable's type. let var_ty = self.fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)); - self.fcx.locals.borrow_mut().insert(nid, LocalTy { - decl_ty: var_ty, - revealed_ty: var_ty - }); + self.fcx.locals.borrow_mut().insert(nid, var_ty); var_ty } Some(typ) => { - // take type that the user specified + // Use the type that the user specified. self.fcx.locals.borrow_mut().insert(nid, typ); - typ.revealed_ty + typ } } } @@ -963,34 +943,24 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { // Add explicitly-declared locals. fn visit_local(&mut self, local: &'gcx hir::Local) { - let local_ty = match local.ty { + let o_ty = match local.ty { Some(ref ty) => { let o_ty = self.fcx.to_ty(&ty); - let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings { - self.fcx.instantiate_opaque_types_from_value( - self.parent_id, - &o_ty - ) - } else { - o_ty - }; - - let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(&revealed_ty); - debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}", - ty.hir_id, o_ty, revealed_ty, c_ty); + let c_ty = self.fcx.inh.infcx.canonicalize_response(&o_ty); + debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty); self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty); - Some(LocalTy { decl_ty: o_ty, revealed_ty }) + Some(o_ty) }, None => None, }; - self.assign(local.span, local.id, local_ty); + self.assign(local.span, local.id, o_ty); - debug!("Local variable {:?} is assigned type {}", + debug!("visit_local: variable {:?} is assigned type {}", local.pat, self.fcx.ty_to_string( - self.fcx.locals.borrow().get(&local.id).unwrap().clone().decl_ty)); + self.fcx.locals.borrow().get(&local.id).unwrap().clone())); intravisit::walk_local(self, local); } @@ -1004,10 +974,10 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { traits::VariableType(p.id)); } - debug!("Pattern binding {} is assigned to {} with type {:?}", + debug!("visit_pat: pattern binding {} is assigned to {} with type {:?}", ident, self.fcx.ty_to_string( - self.fcx.locals.borrow().get(&p.id).unwrap().clone().decl_ty), + self.fcx.locals.borrow().get(&p.id).unwrap().clone()), var_ty); } intravisit::walk_pat(self, p); @@ -1051,14 +1021,14 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env); - // Create the function context. This is either derived from scratch or, + // Create the function context. This is either derived from scratch or, // in the case of closures, based on the outer context. let mut fcx = FnCtxt::new(inherited, param_env, body.value.id); *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let declared_ret_ty = fn_sig.output(); fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(fn_id, &declared_ret_ty); + let revealed_ret_ty = fcx.instantiate_opaque_types_from_return_value(fn_id, &declared_ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( fn_sig.inputs().iter().cloned(), @@ -1076,9 +1046,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fcx.yield_ty = Some(yield_ty); } - let outer_def_id = fcx.tcx.closure_base_def_id(fcx.tcx.hir.local_def_id(fn_id)); - let outer_node_id = fcx.tcx.hir.as_local_node_id(outer_def_id).unwrap(); - GatherLocalsVisitor { fcx: &fcx, parent_id: outer_node_id, }.visit_body(body); + GatherLocalsVisitor { fcx: &fcx, }.visit_body(body); // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { @@ -2074,7 +2042,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { format!("{:?}", self_ptr) } - pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> LocalTy<'tcx> { + pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> { self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| span_bug!(span, "no type for local variable {}", self.tcx.hir.node_to_string(nid)) @@ -2274,16 +2242,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { result } - /// Replace the opaque types from the given value with type variables, - /// and records the `OpaqueTypeMap` for later use during writeback. See + /// Replace the opaque types from the return value of the + /// function with type variables and records the `OpaqueTypeMap` for + /// later use during writeback. See /// `InferCtxt::instantiate_opaque_types` for more details. - fn instantiate_opaque_types_from_value>( + fn instantiate_opaque_types_from_return_value>( &self, parent_id: ast::NodeId, value: &T, ) -> T { let parent_def_id = self.tcx.hir.local_def_id(parent_id); - debug!("instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})", + debug!("instantiate_opaque_types_from_return_value(parent_def_id={:?}, value={:?})", parent_def_id, value); @@ -3724,7 +3693,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { adt_ty } - /// Invariant: /// If an expression has any sub-expressions that result in a type error, /// inspecting that expression's type with `ty.references_error()` will return @@ -3776,7 +3744,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(self.diverges.get() | old_diverges); self.has_errors.set(self.has_errors.get() | old_has_errors); - debug!("type of {} is...", self.tcx.hir.node_to_string(expr.id)); + debug!("type of {} is ...", self.tcx.hir.node_to_string(expr.id)); debug!("... {:?}, expected is {:?}", ty, expected); ty @@ -3809,7 +3777,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let referent_ty = self.check_expr_with_expectation(subexpr, expected_inner); tcx.mk_box(referent_ty) } - hir::ExprKind::Lit(ref lit) => { self.check_lit(&lit, expected) } @@ -4003,7 +3970,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ctxt.may_break = true; - // the type of a `break` is always `!`, since it diverges + // The type of a `break` is always `!`, since it diverges. tcx.types.never } else { // Otherwise, we failed to find the enclosing loop; @@ -4467,12 +4434,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // See #44848. let ref_bindings = local.pat.contains_explicit_ref_binding(); - let local_ty = self.local_ty(init.span, local.id).revealed_ty; + let local_ty = self.local_ty(init.span, local.id); if let Some(m) = ref_bindings { // Somewhat subtle: if we have a `ref` binding in the pattern, // we want to avoid introducing coercions for the RHS. This is // both because it helps preserve sanity and, in the case of - // ref mut, for soundness (issue #23116). In particular, in + // `ref mut`, for soundness (issue #23116). In particular, in // the latter case, we need to be clear that the type of the // referent for the reference that results is *equal to* the // type of the place it is referencing, and not some @@ -4486,7 +4453,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_decl_local(&self, local: &'gcx hir::Local) { - let t = self.local_ty(local.span, local.id).decl_ty; + let t = self.local_ty(local.span, local.id); self.write_ty(local.hir_id, t); if let Some(ref init) = local.init { @@ -5062,7 +5029,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match def { Def::Local(nid) | Def::Upvar(nid, ..) => { - let ty = self.local_ty(span, nid).decl_ty; + let ty = self.local_ty(span, nid); let ty = self.normalize_associated_types_in(span, &ty); self.write_ty(self.tcx.hir.node_to_hir_id(node_id), ty); return (ty, def); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index d968bf222aa09..e5a1ff6bc6b21 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -286,7 +286,7 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { fn visit_local(&mut self, l: &'gcx hir::Local) { intravisit::walk_local(self, l); - let var_ty = self.fcx.local_ty(l.span, l.id).decl_ty; + let var_ty = self.fcx.local_ty(l.span, l.id); let var_ty = self.resolve(&var_ty, &l.span); self.write_ty_to_tables(l.hir_id, var_ty); } @@ -425,31 +425,31 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { instantiated_ty, ) } else { - // prevent + // Prevent // * `fn foo() -> Foo` // * `fn foo() -> Foo` - // from being defining + // from being defining. // Also replace all generic params with the ones from the existential type - // definition so + // definition so that // ```rust // existential type Foo: 'static; // fn foo() -> Foo { .. } // ``` - // figures out the concrete type with `U`, but the stored type is with `T` + // figures out the concrete type with `U`, but the stored type is with `T`. instantiated_ty.fold_with(&mut BottomUpFolder { tcx: self.tcx().global_tcx(), fldop: |ty| { - trace!("checking type {:?}: {:#?}", ty, ty.sty); - // find a type parameter + trace!("visit_opaque_types: checking type {:?}: {:#?}", ty, ty.sty); + // Find a type parameter. if let ty::Param(..) = ty.sty { - // look it up in the substitution list + // Look it up in the substitution list. assert_eq!(opaque_defn.substs.len(), generics.params.len()); for (subst, param) in opaque_defn.substs.iter().zip(&generics.params) { if let UnpackedKind::Type(subst) = subst.unpack() { if subst == ty { - // found it in the substitution list, replace with the - // parameter from the existential type + // Found it in the substitution list, replace with the + // parameter from the existential type. return self.tcx() .global_tcx() .mk_ty_param(param.index, param.name); @@ -520,12 +520,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty { if def_id == defin_ty_def_id { - // Concrete type resolved to the existential type itself - // Force a cycle error + // Concrete type itself resolved to the existential type. + // Force a cycle error. self.tcx().at(span).type_of(defin_ty_def_id); } } + debug!("visit_opaque_types: bar1: {:?} {:?} {:?}", span, def_id, definition_ty); let old = self.tables .concrete_existential_types .insert(def_id, definition_ty); @@ -533,8 +534,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if old != definition_ty { span_bug!( span, - "visit_opaque_types tried to write \ - different types for the same existential type: {:?}, {:?}, {:?}", + "visit_opaque_types: tried to write different types \ + for the same existential type: {:?}, {:?}, {:?}", def_id, definition_ty, old, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index be09cfce8cae6..46b9b9555b67d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1109,7 +1109,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty }) } -fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) { +fn report_assoc_ty_in_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) { span_err!( tcx.sess, span, @@ -1148,7 +1148,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { .impl_trait_ref(tcx.hir.get_parent_did(node_id)) .is_none() { - report_assoc_ty_on_inherent_impl(tcx, item.span); + report_assoc_ty_in_inherent_impl(tcx, item.span); } find_existential_constraints(tcx, def_id) @@ -1158,7 +1158,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { .impl_trait_ref(tcx.hir.get_parent_did(node_id)) .is_none() { - report_assoc_ty_on_inherent_impl(tcx, item.span); + report_assoc_ty_in_inherent_impl(tcx, item.span); } icx.to_ty(ty) @@ -1330,7 +1330,7 @@ fn find_existential_constraints<'a, 'tcx>( impl<'a, 'tcx> ConstraintLocator<'a, 'tcx> { fn check(&mut self, def_id: DefId) { trace!("checking {:?}", def_id); - // don't try to check items that cannot possibly constrain the type + // Don't try to check items that cannot possibly constrain the type. if !self.tcx.has_typeck_tables(def_id) { trace!("no typeck tables for {:?}", def_id); return; @@ -1342,11 +1342,11 @@ fn find_existential_constraints<'a, 'tcx>( .get(&self.def_id) .cloned(); if let Some(ty) = ty { - // FIXME(oli-obk): trace the actual span from inference to improve errors + // FIXME(oli-obk): trace the actual span from inference to improve errors. let span = self.tcx.def_span(def_id); if let Some((prev_span, prev_ty)) = self.found { if ty != prev_ty { - // found different concrete types for the existential type + // Found different concrete types for the existential type. let mut err = self.tcx.sess.struct_span_err( span, "defining existential type use differs from previous", @@ -1367,7 +1367,7 @@ fn find_existential_constraints<'a, 'tcx>( } fn visit_item(&mut self, it: &'tcx Item) { let def_id = self.tcx.hir.local_def_id(it.id); - // the existential type itself or its children are not within its reveal scope + // The existential type itself or its children are not within its reveal scope. if def_id != self.def_id { self.check(def_id); intravisit::walk_item(self, it); @@ -1375,7 +1375,7 @@ fn find_existential_constraints<'a, 'tcx>( } fn visit_impl_item(&mut self, it: &'tcx ImplItem) { let def_id = self.tcx.hir.local_def_id(it.id); - // the existential type itself or its children are not within its reveal scope + // The existential type itself or its children are not within its reveal scope. if def_id != self.def_id { self.check(def_id); intravisit::walk_impl_item(self, it); @@ -1750,7 +1750,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,