From f0b0a4ff2a4102e9429320a7f4d76d7c834f5bf5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 13 Mar 2016 12:11:16 +0100 Subject: [PATCH 1/3] Normalize return type when checking for E0269 Fixes #31597 --- src/librustc/middle/liveness.rs | 14 ++++++++++++-- src/test/run-pass/issue-31597.rs | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-31597.rs diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 04240bf2875..a24b4952987 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -113,6 +113,8 @@ use dep_graph::DepNode; use middle::def::*; use middle::pat_util; use middle::ty::{self, TyCtxt}; +use middle::traits; +use middle::infer; use lint; use util::nodemap::NodeMap; @@ -1490,9 +1492,17 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match fn_ret { ty::FnConverging(t_ret) - if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => { + if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => { - if t_ret.is_nil() { + let infcx = infer::new_infer_ctxt(&self.ir.tcx, &self.ir.tcx.tables, None); + let mut selcx = traits::SelectionContext::new(&infcx); + let cause = traits::ObligationCause::dummy(); + + let norm = traits::normalize(&mut selcx, + cause, + &t_ret); + + if norm.value.is_nil() { // for nil return types, it is ok to not return a value expl. } else { let ends_with_stmt = match body.expr { diff --git a/src/test/run-pass/issue-31597.rs b/src/test/run-pass/issue-31597.rs new file mode 100644 index 00000000000..132d476f9dc --- /dev/null +++ b/src/test/run-pass/issue-31597.rs @@ -0,0 +1,23 @@ +// Copyright 2016 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. + +trait Make { + type Out; + + fn make() -> Self::Out; +} + +impl Make for () { + type Out = (); + + fn make() -> Self::Out {} +} + +fn main() {} From 4dbb01ff65b87ae7130b4180d3fe46c9f2fc358f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 13 Mar 2016 14:42:13 +0100 Subject: [PATCH 2/3] Use `fully_normalize`, unwrapping its result --- src/librustc/middle/liveness.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index a24b4952987..5c1b64ac002 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -112,7 +112,7 @@ use self::VarKind::*; use dep_graph::DepNode; use middle::def::*; use middle::pat_util; -use middle::ty::{self, TyCtxt}; +use middle::ty::{self, TyCtxt, ParameterEnvironment}; use middle::traits; use middle::infer; use lint; @@ -1494,15 +1494,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ty::FnConverging(t_ret) if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => { - let infcx = infer::new_infer_ctxt(&self.ir.tcx, &self.ir.tcx.tables, None); - let mut selcx = traits::SelectionContext::new(&infcx); + let param_env = ParameterEnvironment::for_item(&self.ir.tcx, id); + let infcx = infer::new_infer_ctxt(&self.ir.tcx, + &self.ir.tcx.tables, + Some(param_env)); let cause = traits::ObligationCause::dummy(); + let norm = traits::fully_normalize(&infcx, + cause, + &t_ret); - let norm = traits::normalize(&mut selcx, - cause, - &t_ret); - - if norm.value.is_nil() { + if norm.unwrap().is_nil() { // for nil return types, it is ok to not return a value expl. } else { let ends_with_stmt = match body.expr { From 96d9408dd9c932d5302c357d37f1a0262dcb51a9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 16 Mar 2016 13:22:35 +0100 Subject: [PATCH 3/3] Resolve conflicts and extend the test --- src/librustc/middle/liveness.rs | 5 +++-- src/test/run-pass/issue-31597.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 5c1b64ac002..0bfb830efc1 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -113,7 +113,7 @@ use dep_graph::DepNode; use middle::def::*; use middle::pat_util; use middle::ty::{self, TyCtxt, ParameterEnvironment}; -use middle::traits; +use middle::traits::{self, ProjectionMode}; use middle::infer; use lint; use util::nodemap::NodeMap; @@ -1497,7 +1497,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let param_env = ParameterEnvironment::for_item(&self.ir.tcx, id); let infcx = infer::new_infer_ctxt(&self.ir.tcx, &self.ir.tcx.tables, - Some(param_env)); + Some(param_env), + ProjectionMode::Any); let cause = traits::ObligationCause::dummy(); let norm = traits::fully_normalize(&infcx, cause, diff --git a/src/test/run-pass/issue-31597.rs b/src/test/run-pass/issue-31597.rs index 132d476f9dc..9acd6384b75 100644 --- a/src/test/run-pass/issue-31597.rs +++ b/src/test/run-pass/issue-31597.rs @@ -20,4 +20,18 @@ impl Make for () { fn make() -> Self::Out {} } +// Also make sure we don't hit an ICE when the projection can't be known +fn f() -> ::Out { loop {} } + +// ...and that it works with a blanket impl +trait Tr { + type Assoc; +} + +impl Tr for T { + type Assoc = (); +} + +fn g() -> ::Assoc { } + fn main() {}