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 51ade33f74cf..2c49dbd969d5 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -307,8 +307,20 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_type(local_decl, local_decl.ty); for (user_ty, span) in local_decl.user_ty.projections_and_spans() { + let ty = if !local_decl.is_nonref_binding() { + // If we have a binding of the form `let ref x: T = ..` then remove the outermost + // reference so we can check the type annotation for the remaining type. + if let ty::Ref(_, rty, _) = local_decl.ty.sty { + rty + } else { + bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty); + } + } else { + local_decl.ty + }; + if let Err(terr) = self.cx.relate_type_and_user_type( - local_decl.ty, + ty, ty::Variance::Invariant, user_ty, Locations::All(*span), diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index ad4e5a50dcd1..41718cfc8701 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -141,6 +141,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { None, remainder_span, lint_level, slice::from_ref(&pattern), ArmHasGuard(false), None); + debug!("ast_block_stmts: pattern={:?}", pattern); this.visit_bindings( &pattern, &PatternTypeProjections::none(), diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 92642dff3dc6..085c58ef5ff6 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -409,6 +409,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); let mut scope = self.source_scope; let num_patterns = patterns.len(); + debug!("declare_bindings: patterns={:?}", patterns); self.visit_bindings( &patterns[0], &PatternTypeProjections::none(), @@ -499,6 +500,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { &PatternTypeProjections<'tcx>, ), ) { + debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty); match *pattern.kind { PatternKind::Binding { mutability, @@ -509,19 +511,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ref subpattern, .. } => { - let pattern_ref_binding; // sidestep temp lifetime limitations. - let binding_user_ty = match mode { - BindingMode::ByValue => { pattern_user_ty } - BindingMode::ByRef(..) => { - // If this is a `ref` binding (e.g., `let ref - // x: T = ..`), then the type of `x` is not - // `T` but rather `&T`. - pattern_ref_binding = pattern_user_ty.ref_binding(); - &pattern_ref_binding - } - }; - - f(self, mutability, name, mode, var, pattern.span, ty, binding_user_ty); + f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty); if let Some(subpattern) = subpattern.as_ref() { self.visit_bindings(subpattern, pattern_user_ty, f); } @@ -565,6 +555,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field); + debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty); self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f); } } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 00de40d8cff8..6d562c69b2dc 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -79,11 +79,6 @@ impl<'tcx> PatternTypeProjections<'tcx> { PatternTypeProjections { contents: vec![] } } - pub(crate) fn ref_binding(&self) -> Self { - // FIXME(#55401): ignore for now - PatternTypeProjections { contents: vec![] } - } - fn map_projs(&self, mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>) -> Self @@ -803,7 +798,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) { - debug!("lower_variant_or_leaf: user_ty={:?} span={:?}", user_ty, span); + debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span); kind = PatternKind::AscribeUserType { subpattern: Pattern { span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ff4574eb283f..36de41ef8a17 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2388,6 +2388,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { let ty = self.to_ty(ast_ty); + debug!("to_ty_saving_user_provided_ty: ty={:?}", ty); // If the type given by the user has free regions, save it for // later, since NLL would like to enforce those. Also pass in @@ -2398,6 +2399,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // already sufficiently enforced with erased regions. =) if ty.has_free_regions() || ty.has_projections() { let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty)); + debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty); self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty); } diff --git a/src/test/ui/nll/issue-55401.rs b/src/test/ui/nll/issue-55401.rs new file mode 100644 index 000000000000..2fa234491087 --- /dev/null +++ b/src/test/ui/nll/issue-55401.rs @@ -0,0 +1,8 @@ +#![feature(nll)] + +fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + let (ref y, _z): (&'a u32, u32) = (&22, 44); + *y //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr new file mode 100644 index 000000000000..9e50db7b6045 --- /dev/null +++ b/src/test/ui/nll/issue-55401.stderr @@ -0,0 +1,11 @@ +error: unsatisfied lifetime constraints + --> $DIR/issue-55401.rs:5:5 + | +LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let (ref y, _z): (&'a u32, u32) = (&22, 44); +LL | *y //~ ERROR + | ^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error +